This commit is contained in:
2020-08-22 12:21:18 +02:00
parent 12c3383b55
commit 54e80707b2
11 changed files with 132 additions and 47 deletions

View File

@@ -2,6 +2,7 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self'"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; connect-src 'self'">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>
</head> </head>

View File

@@ -14,6 +14,7 @@
"@babel/preset-typescript": "^7.10.4", "@babel/preset-typescript": "^7.10.4",
"@hot-loader/react-dom": "^16.13.0", "@hot-loader/react-dom": "^16.13.0",
"@types/html-webpack-plugin": "^3.2.3", "@types/html-webpack-plugin": "^3.2.3",
"@types/jszip": "^3.4.1",
"@types/openpgp": "^4.4.12", "@types/openpgp": "^4.4.12",
"@types/react": "^16.9.46", "@types/react": "^16.9.46",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
@@ -39,6 +40,7 @@
"webpack-subresource-integrity": "^1.4.1" "webpack-subresource-integrity": "^1.4.1"
}, },
"dependencies": { "dependencies": {
"jszip": "^3.5.0",
"nanoid": "^3.1.12", "nanoid": "^3.1.12",
"openpgp": "^4.10.7", "openpgp": "^4.10.7",
"react": "^16.13.1", "react": "^16.13.1",

View File

@@ -14,22 +14,13 @@ import {
ShareAltOutlined, ShareAltOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { FileType } from '../contexts/Encryption'; import { FileType } from '../contexts/Encryption';
import { downloadLink } from '../helpers/files';
interface Props { interface Props {
remove: () => void; remove: () => void;
file: FileType; file: FileType;
} }
const downloadLink = (name: string, blob: Blob) => {
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
};
const icons: {[name: string]: any} = { const icons: {[name: string]: any} = {
encrypting: <SyncOutlined spin />, encrypting: <SyncOutlined spin />,
failed: <IssuesCloseOutlined />, failed: <IssuesCloseOutlined />,

View File

@@ -1,25 +1,39 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { List, Empty } from 'antd'; import { Space, List, Empty, Button } from 'antd';
import { DownloadOutlined } from '@ant-design/icons';
import EncryptionContext from '../contexts/Encryption'; import EncryptionContext from '../contexts/Encryption';
import useDownloadAll from '../hooks/useDownloadAll';
import File from './File'; import File from './File';
const Encrypt: React.FC = () => { const Encrypt: React.FC = () => {
const { files, deleteFile } = useContext(EncryptionContext); const { files, deleteFile } = useContext(EncryptionContext);
const { status, downloadAll } = useDownloadAll();
if (Object.keys(files).length === 0) { if (Object.keys(files).length === 0) {
return <Empty /> return <Empty />
} }
return ( return (
<List> <Space direction="vertical" style={{width: '100%' }}>
{Object.entries(files).map(([id, file]) => ( <List>
<File {Object.entries(files).map(([id, file]) => (
key={id} <File
file={file} key={id}
remove={() => deleteFile(id)} file={file}
/> remove={() => deleteFile(id)}
))} />
</List> ))}
</List>
{downloadAll && (
<Button
icon={<DownloadOutlined />}
disabled={status !== 'ready'}
onClick={downloadAll}
>
Download all
</Button>
)}
</Space>
); );
}; };

View File

@@ -1,7 +1,6 @@
import React, { createContext } from 'react'; import React, { createContext } from 'react';
const data = require('../../data.json'); const data = require('../../data.json');
console.log('d', data);
interface GithubContextType { interface GithubContextType {
username: string; username: string;
@@ -13,7 +12,7 @@ const GithubProvider: React.FC = ({
children, children,
}) => ( }) => (
<GithubContext.Provider <GithubContext.Provider
value={{ data }} value={{ ...data }}
> >
{children} {children}
</GithubContext.Provider> </GithubContext.Provider>

9
src/helpers/files.ts Normal file
View File

@@ -0,0 +1,9 @@
export const downloadLink = (name: string, blob: Blob) => {
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement('a');
downloadLink.href = url;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
};

View File

@@ -0,0 +1,33 @@
import { useState, useContext, useCallback } from 'react';
import EncryptionContext from '../contexts/Encryption';
import Zip from 'jszip';
import { downloadLink } from '../helpers/files';
type Statuses = 'packing' | 'ready';
const useDownloadAll = () => {
const [status, setStatus] = useState<Statuses>('ready');
const { files } = useContext(EncryptionContext);
const allFilesReady = Object.values(files).filter(f => f.link).length > 1;
const downloadAll = useCallback(() => {
setStatus('packing');
const run = async () => {
const zip = new Zip();
Object.values(files).map((file) => {
zip.file(file.name, file.link!);
});
const link = await zip.generateAsync({ type: 'blob' });
setStatus('ready');
downloadLink('all-files.zip', link);
};
run();
}, [files]);
return {
status,
downloadAll: allFilesReady ? downloadAll : undefined,
};
};
export default useDownloadAll;

View File

@@ -5,26 +5,28 @@ import 'antd/dist/antd.css';
import { render } from 'react-dom'; import { render } from 'react-dom';
import App from './App'; import App from './App';
OfflinePluginRuntime.install({ if (!__DEV__) {
onUpdating: () => { OfflinePluginRuntime.install({
console.log('SW Event:', 'onUpdating'); onUpdating: () => {
}, console.log('SW Event:', 'onUpdating');
onUpdateReady: () => { },
console.log('SW Event:', 'onUpdateReady'); onUpdateReady: () => {
OfflinePluginRuntime.applyUpdate(); console.log('SW Event:', 'onUpdateReady');
}, OfflinePluginRuntime.applyUpdate();
onUpdated: () => { },
notification.success({ onUpdated: () => {
message: 'Your app has been updated', notification.success({
}); message: 'Your app has been updated',
}, });
onUpdateFailed: () => { },
notification.warn({ onUpdateFailed: () => {
message: 'Could not update to the latest version', notification.warn({
}); message: 'Could not update to the latest version',
console.log('SW Event:', 'onUpdateFailed'); });
} console.log('SW Event:', 'onUpdateFailed');
}); }
});
}
const root = document.createElement('div'); const root = document.createElement('div');
root.style.height = '100%'; root.style.height = '100%';

View File

@@ -1,5 +1,5 @@
import React, { useContext, useEffect } from 'react'; import React, { useContext, useEffect } from 'react';
import { Divider, PageHeader } from 'antd'; import { Divider } from 'antd';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import Add from '../components/Add'; import Add from '../components/Add';
import FileList from '../components/FileList'; import FileList from '../components/FileList';

View File

@@ -1,4 +1,4 @@
import { Configuration } from 'webpack'; import webpack, { Configuration } from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin';
import SriPlugin from 'webpack-subresource-integrity'; import SriPlugin from 'webpack-subresource-integrity';
import path from 'path'; import path from 'path';
@@ -46,9 +46,9 @@ const config: Configuration = {
minify: true, minify: true,
template: path.join(__dirname, 'html.html'), template: path.join(__dirname, 'html.html'),
}), }),
new OfflinePlugin({ ...(__DEV__ ? [] : [new OfflinePlugin({
events: true, events: true,
}), })]),
], ],
module: { module: {
rules: [{ rules: [{

View File

@@ -1407,6 +1407,13 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
"@types/jszip@^3.4.1":
version "3.4.1"
resolved "https://registry.yarnpkg.com/@types/jszip/-/jszip-3.4.1.tgz#e7a4059486e494c949ef750933d009684227846f"
integrity sha512-TezXjmf3lj+zQ651r6hPqvSScqBLvyPI9FxdXBqpEwBijNGQ2NXpaFW/7joGzveYkKQUil7iiDHLo6LV71Pc0A==
dependencies:
jszip "*"
"@types/minimatch@*": "@types/minimatch@*":
version "3.0.3" version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -4498,6 +4505,11 @@ iferr@^0.1.5:
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
import-fresh@^2.0.0: import-fresh@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@@ -5030,6 +5042,16 @@ jsprim@^1.2.2:
json-schema "0.2.3" json-schema "0.2.3"
verror "1.10.0" verror "1.10.0"
jszip@*, jszip@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6"
integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==
dependencies:
lie "~3.3.0"
pako "~1.0.2"
readable-stream "~2.3.6"
set-immediate-shim "~1.0.1"
killable@^1.0.1: killable@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -5079,6 +5101,13 @@ levn@~0.3.0:
prelude-ls "~1.1.2" prelude-ls "~1.1.2"
type-check "~0.3.2" type-check "~0.3.2"
lie@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
dependencies:
immediate "~3.0.5"
load-bmfont@^1.3.1, load-bmfont@^1.4.0: load-bmfont@^1.3.1, load-bmfont@^1.4.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9" resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9"
@@ -5854,7 +5883,7 @@ pako@^0.2.5:
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=
pako@^1.0.5, pako@~1.0.5: pako@^1.0.5, pako@~1.0.2, pako@~1.0.5:
version "1.0.11" version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
@@ -7628,6 +7657,11 @@ set-blocking@^2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
set-immediate-shim@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
set-value@^2.0.0, set-value@^2.0.1: set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"