Skip to content

Commit 66a823d

Browse files
committed
Building blocks for a password vault
1 parent 1a49324 commit 66a823d

File tree

20 files changed

+341
-29
lines changed

20 files changed

+341
-29
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"@testing-library/user-event": "^14.4.3",
1616
"react": "^18.2.0",
1717
"react-dom": "^18.2.0",
18-
"react-router-dom": "^6.4.5",
18+
"react-router-dom": "^6.5.0",
1919
"react-scripts": "^5.0.1",
2020
"react-virtualized": "^9.22.3",
2121
"web-vitals": "^3.1.0"

src/components/App/index.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const Generate = lazy(() => import('../../routes/Generate'));
3030
const About = lazy(() => import('../../routes/About'));
3131
const Settings = lazy(() => import('../../routes/Settings'));
3232
const Advisor = lazy(() => import('../../routes/Advisor'));
33+
const Vault = lazy(() => import('../../routes/Vault'));
3334
const NotFound = lazy(() => import('../../routes/NotFound'));
3435

3536
const App = () => {
@@ -127,6 +128,8 @@ const App = () => {
127128
<Route exact path="/advanced" element={<Advanced />} />
128129
<Route exact path="/generate" element={<Generate />} />
129130
<Route exact path="/advisor" element={<Advisor />} />
131+
{/* eslint-disable-next-line no-underscore-dangle */}
132+
{window.__TAURI__ ? (<Route exact path="/vault" element={<Vault />} />) : null}
130133
<Route exact path="/settings" element={<Settings />} />
131134
<Route exact path="/about" element={<About />} />
132135
<Route path="*" element={<NotFound />} />

src/components/ClippedDrawer/index.jsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import LightbulbIcon from '@mui/icons-material/Lightbulb';
1515
import InfoIcon from '@mui/icons-material/Info';
1616
import SettingsIcon from '@mui/icons-material/Settings';
1717
import AttachMoneyIcon from '@mui/icons-material/AttachMoney';
18+
import FolderIcon from '@mui/icons-material/Folder';
1819
import { useNavigate } from 'react-router-dom';
1920
import { MainContext } from '../../contexts/MainContextProvider';
2021
import { openWebSite } from '../../reducers/MainReducer/Actions';
@@ -148,12 +149,36 @@ const ClippedDrawer = () => {
148149
{textVisible ? <ListItemText primary={language.advisor} /> : null}
149150
</ListItemButton>
150151
</ListItem>
152+
{/* eslint-disable-next-line no-underscore-dangle */}
153+
{window.__TAURI__ ? (
154+
<ListItem disablePadding sx={{ display: textVisible ? 'block' : null }}>
155+
<ListItemButton
156+
selected={pageIndex === 4}
157+
onClick={() => navigate('/vault')}
158+
sx={{
159+
minHeight: 48,
160+
justifyContent: textVisible ? 'initial' : 'center',
161+
px: 2.5,
162+
}}
163+
>
164+
<ListItemIcon
165+
sx={{
166+
minWidth: textVisible ? null : 0,
167+
mr: textVisible ? null : 'auto',
168+
}}
169+
>
170+
<FolderIcon />
171+
</ListItemIcon>
172+
{textVisible ? <ListItemText primary={language.vault} /> : null}
173+
</ListItemButton>
174+
</ListItem>
175+
) : null}
151176
</List>
152177
<Divider />
153178
<List>
154179
<ListItem disablePadding sx={{ display: textVisible ? 'block' : null }}>
155180
<ListItemButton
156-
selected={pageIndex === 4}
181+
selected={pageIndex === 5}
157182
onClick={() => navigate('/settings')}
158183
sx={{
159184
minHeight: 48,
@@ -197,7 +222,7 @@ const ClippedDrawer = () => {
197222
</ListItem>
198223
<ListItem disablePadding sx={{ display: textVisible ? 'block' : null }}>
199224
<ListItemButton
200-
selected={pageIndex === 5}
225+
selected={pageIndex === 6}
201226
onClick={() => navigate('/about')}
202227
sx={{
203228
minHeight: 48,
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { useContext, useState } from 'react';
2+
import Dialog from '@mui/material/Dialog';
3+
import TextField from '@mui/material/TextField';
4+
import DialogContent from '@mui/material/DialogContent';
5+
import DialogTitle from '@mui/material/DialogTitle';
6+
import DialogActions from '@mui/material/DialogActions';
7+
import Button from '@mui/material/Button';
8+
import { MainContext } from '../../contexts/MainContextProvider';
9+
10+
const CreateVaultDialog = ({ open, onCreate, onClose }) => {
11+
const [state] = useContext(MainContext);
12+
const language = state.languages[state.languageIndex];
13+
14+
const [key, setKey] = useState('');
15+
16+
/**
17+
* Close the dialog
18+
*/
19+
const handleClose = () => {
20+
if (onClose) {
21+
onClose();
22+
}
23+
setKey('');
24+
};
25+
26+
/**
27+
* Create a new vault
28+
*/
29+
const create = () => {
30+
if (onCreate) {
31+
onCreate(key);
32+
}
33+
handleClose();
34+
};
35+
36+
return (
37+
<Dialog
38+
open={open}
39+
onClose={handleClose}
40+
aria-labelledby="create-vault-dialog-title"
41+
>
42+
<DialogTitle id="create-vault-dialog-title">
43+
{language.createVault}
44+
</DialogTitle>
45+
<DialogContent>
46+
<TextField
47+
sx={{ mt: 2 }}
48+
value={key}
49+
error={key.length === 0}
50+
label={language.decryptionKey}
51+
onChange={(e) => setKey(e.target.value)}
52+
autoComplete="off"
53+
variant="outlined"
54+
/>
55+
</DialogContent>
56+
<DialogActions>
57+
<Button onClick={handleClose}>
58+
{language.cancel}
59+
</Button>
60+
<Button
61+
onClick={create}
62+
autoFocus
63+
disabled={key.length === 0}
64+
>
65+
{language.ok}
66+
</Button>
67+
</DialogActions>
68+
</Dialog>
69+
);
70+
};
71+
72+
export default CreateVaultDialog;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { createContext, useReducer } from 'react';
2+
import VaultReducer from '../../reducers/PasswordReducer';
3+
4+
const initState = {
5+
vault: null,
6+
};
7+
8+
export const VaultContext = createContext(initState);
9+
10+
const VaultContextProvider = ({ children }) => {
11+
const [state, dispatch] = useReducer(VaultReducer, initState);
12+
13+
return (
14+
// eslint-disable-next-line react/jsx-no-constructed-context-values
15+
<VaultContext.Provider value={[state, dispatch]}>
16+
{children}
17+
</VaultContext.Provider>
18+
);
19+
};
20+
21+
export default VaultContextProvider;

src/index.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ import '@fontsource/roboto/500.css';
99
import '@fontsource/roboto/700.css';
1010
import MainContextProvider from './contexts/MainContextProvider';
1111
import PasswordContextProvider from './contexts/PasswordContextProvider';
12+
import VaultContextProvider from './contexts/VaultContextProvider';
1213

1314
const root = ReactDOM.createRoot(document.getElementById('root'));
1415
root.render(
1516
<React.StrictMode>
1617
<MainContextProvider>
1718
<PasswordContextProvider>
18-
<App />
19+
<VaultContextProvider>
20+
<App />
21+
</VaultContextProvider>
1922
</PasswordContextProvider>
2023
</MainContextProvider>
2124
</React.StrictMode>,

src/languages/de_de.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,11 @@
8181
"downloadApp": "Laden Sie die Desktop-Anwendung herunter",
8282
"languageSelector": "Sprachauswahl im Menü",
8383
"fixedMenu": "Festes Menü",
84-
"runningLatestVersion": "Sie verwenden die neueste Version von Advanced PassGen!"
84+
"runningLatestVersion": "Sie verwenden die neueste Version von Advanced PassGen!",
85+
"vault": "Tresor",
86+
"open": "Öffnen",
87+
"new": "Neu",
88+
"save": "Speichern",
89+
"createVault": "Tresor erstellen",
90+
"decryptionKey": "Entschlüsselungsschlüssel"
8591
}

src/languages/en_us.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,11 @@
8181
"downloadApp": "Download the desktop application",
8282
"languageSelector": "Language selector in the top bar",
8383
"fixedMenu": "Fixed menu",
84-
"runningLatestVersion": "You are using the latest version!"
84+
"runningLatestVersion": "You are using the latest version!",
85+
"vault": "Vault",
86+
"open": "Open",
87+
"new": "New",
88+
"save": "Save",
89+
"createVault": "Create vault",
90+
"decryptionKey": "Decryption key"
8591
}

src/languages/fr_fr.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,11 @@
8181
"downloadApp": "Télécharger l'application desktop",
8282
"languageSelector": "Sélecteur de langue dans la barre du haut",
8383
"fixedMenu": "Menu fixe",
84-
"runningLatestVersion": "Vous utilisez la dernière version!"
84+
"runningLatestVersion": "Vous utilisez la dernière version!",
85+
"vault": "Coffre-fort",
86+
"open": "Ouvrir",
87+
"new": "Nouveau",
88+
"save": "Enregistrer",
89+
"createVault": "Créer un coffre-fort",
90+
"decryptionKey": "Clé de déchiffrement"
8591
}

src/languages/jp_jp.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,11 @@
8181
"downloadApp": "デスクトップ アプリケーションをダウンロードする",
8282
"languageSelector": "トップバーの言語セレクター",
8383
"fixedMenu": "固定メニュー",
84-
"runningLatestVersion": "最新バージョンを実行しています。"
84+
"runningLatestVersion": "最新バージョンを実行しています。",
85+
"vault": "金庫",
86+
"open": "開く",
87+
"new": "新しい",
88+
"save": "セーブ",
89+
"createVault": "金庫を作成する",
90+
"decryptionKey": "復号キー"
8591
}

0 commit comments

Comments
 (0)