Skip to content

Commit 8126886

Browse files
Major 5.0 (#469)
* Advanced generator, UI overhaul (#449) * Major overhaul: - Added advanced generator - Removed "Insert and copy" feature - Moved settings to extension options - General refactoring * Updated custom character options for default generator (#447) * Added state save for advanced generator mode * Fixed state save for advanced password generator * Updated extension description * Minor UI fixes: - Fixed Options UI not displaying in Google Chrome - Fixed Quick Options menus overflowing on some locales - Fixed Advanced generator configuration UI clipping when window height is too small - Fixed divider in Options UI taking up all available space * Minor UI/UX changes and fixes: - Fixed locale in Advanced generator toast notifications - Added toast notification for copying a single password in Advanced generator - Moved custom characters input lables to placeholders - Fixed minor type issues - Removed duplicate "About" text - Fixed input fields alignment in Options - Added "disabled" state for "Include Custom" option in Quick settings * Bump @typescript-eslint/parser from 8.16.0 to 8.19.1 (#468) Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 8.16.0 to 8.19.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.19.1/packages/parser) --- updated-dependencies: - dependency-name: "@typescript-eslint/parser" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @eslint/js from 9.16.0 to 9.18.0 (#467) Bumps [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) from 9.16.0 to 9.18.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/commits/v9.18.0/packages/js) --- updated-dependencies: - dependency-name: "@eslint/js" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @fluentui/react-components from 9.56.3 to 9.57.0 (#466) Bumps [@fluentui/react-components](https://github.com/microsoft/fluentui) from 9.56.3 to 9.57.0. - [Release notes](https://github.com/microsoft/fluentui/releases) - [Changelog](https://github.com/microsoft/fluentui/blob/master/azure-pipelines.release.yml) - [Commits](https://github.com/microsoft/fluentui/compare/@fluentui/react-components_v9.56.3...@fluentui/react-components_v9.57.0) --- updated-dependencies: - dependency-name: "@fluentui/react-components" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wxt from 0.19.17 to 0.19.24 (#465) Bumps [wxt](https://github.com/wxt-dev/wxt) from 0.19.17 to 0.19.24. - [Release notes](https://github.com/wxt-dev/wxt/releases) - [Commits](wxt-dev/wxt@wxt-v0.19.17...wxt-v0.19.24) --- updated-dependencies: - dependency-name: wxt dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump eslint from 9.16.0 to 9.18.0 (#464) Bumps [eslint](https://github.com/eslint/eslint) from 9.16.0 to 9.18.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](eslint/eslint@v9.16.0...v9.18.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump eslint-plugin-react from 7.37.2 to 7.37.4 (#463) Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.37.2 to 7.37.4. - [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases) - [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md) - [Commits](jsx-eslint/eslint-plugin-react@v7.37.2...v7.37.4) --- updated-dependencies: - dependency-name: eslint-plugin-react dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Eugene Fox <eugene.xfox@outlook.com> * Bump typescript from 5.7.2 to 5.7.3 (#462) Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3. - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml) - [Commits](microsoft/TypeScript@v5.7.2...v5.7.3) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Eugene Fox <eugene.xfox@outlook.com> * Bump @typescript-eslint/eslint-plugin from 8.16.0 to 8.19.1 (#461) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 8.16.0 to 8.19.1. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.19.1/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump wdzeng/chrome-extension from 1.2.4 to 1.3.0 (#450) * Bump wdzeng/chrome-extension from 1.2.4 to 1.3.0 Bumps [wdzeng/chrome-extension](https://github.com/wdzeng/chrome-extension) from 1.2.4 to 1.3.0. - [Release notes](https://github.com/wdzeng/chrome-extension/releases) - [Commits](wdzeng/chrome-extension@v1.2.4...v1.3.0) --- updated-dependencies: - dependency-name: wdzeng/chrome-extension dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Optimized CD workflow --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Eugene Fox <eugene@xfox111.net> * Bump @fluentui/react-icons from 2.0.266 to 2.0.270 (#458) Bumps [@fluentui/react-icons](https://github.com/microsoft/fluentui-system-icons) from 2.0.266 to 2.0.270. - [Changelog](https://github.com/microsoft/fluentui-system-icons/blob/main/fluentui-android-system-icons-release.yml) - [Commits](https://github.com/microsoft/fluentui-system-icons/commits) --- updated-dependencies: - dependency-name: "@fluentui/react-icons" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @wxt-dev/module-react from 1.1.2 to 1.1.3 (#455) Bumps [@wxt-dev/module-react](https://github.com/wxt-dev/wxt/tree/HEAD/packages/module-react) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/wxt-dev/wxt/releases) - [Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/module-react/CHANGELOG.md) - [Commits](https://github.com/wxt-dev/wxt/commits/module-react-v1.1.3/packages/module-react) --- updated-dependencies: - dependency-name: "@wxt-dev/module-react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump globals from 15.12.0 to 15.14.0 (#452) Bumps [globals](https://github.com/sindresorhus/globals) from 15.12.0 to 15.14.0. - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](sindresorhus/globals@v15.12.0...v15.14.0) --- updated-dependencies: - dependency-name: globals dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent c0cab1c commit 8126886

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+53677
-2591
lines changed

.github/workflows/cd_pipeline.yaml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,10 @@ jobs:
101101
with:
102102
name: chrome
103103

104-
- name: Get version from package.json
105-
id: get_version
106-
run: |
107-
extname=`ls password-generator-*-chrome.zip`
108-
echo "filename=$extname" >> "$GITHUB_OUTPUT"
109-
110-
- uses: wdzeng/chrome-extension@v1.2.4
104+
- uses: wdzeng/chrome-extension@v1.3.0
111105
with:
112106
extension-id: jnjobgjobffgmgfnkpkjfjkkfhfikmfl
113-
zip-path: ${{ steps.get_version.outputs.filename }}
107+
zip-path: password-generator-*-chrome.zip
114108
client-id: ${{ secrets.CHROME_CLIENT_ID }}
115109
client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
116110
refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2024 Eugene Fox
3+
Copyright (c) 2025 Eugene Fox
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99
<img alt="Password generator">
1010
</picture>
1111

12-
Extension for web browsers which helps you to easily generate strong passwords in one click
12+
Extension for web browsers which helps you to easily generate strong and customizable passwords in a few clicks
1313

1414
## Features
1515
- Customizable generator
1616
- Clean and simple UI
1717
- Dark mode
18-
- **NEW:** Insert and copy generated password in one click
19-
20-
![Demo](https://cdn.xfox111.net/projects/pwdgen/demo.gif)
18+
- **NEW:** Advanced password generator
19+
- **NEW:** Passphrase generator
2120

2221
## Languages
2322
- Chinese (Simplified)
@@ -93,4 +92,4 @@ If you are interested in fixing issues and contributing directly to the code bas
9392
[![GitHub followers](https://img.shields.io/github/followers/xfox111?label=Follow%20@xfox111&style=social)](https://github.com/xfox111)
9493
[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-%40xfox111-orange)](https://buymeacoffee.com/xfox111)
9594

96-
> ©2024 Eugene Fox. Licensed under [MIT license](https://github.com/XFox111/PasswordGeneratorExtension/blob/main/LICENSE)
95+
> ©2025 Eugene Fox. Licensed under [MIT license](https://github.com/XFox111/PasswordGeneratorExtension/blob/main/LICENSE)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { makeStyles, tokens } from "@fluentui/react-components";
2+
3+
export const useStyles = makeStyles({
4+
root:
5+
{
6+
display: "grid",
7+
gridTemplateColumns: "1fr 1fr",
8+
height: "100vh",
9+
gap: tokens.spacingHorizontalXL,
10+
padding: `${tokens.spacingVerticalXL} ${tokens.spacingHorizontalXL}`,
11+
boxSizing: "border-box",
12+
},
13+
smallRoot:
14+
{
15+
display: "flex",
16+
flexFlow: "column-reverse",
17+
overflowX: "hidden",
18+
overflowY: "auto",
19+
padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalS}`,
20+
},
21+
hideScroll:
22+
{
23+
overflowY: "visible",
24+
maxHeight: "unset",
25+
},
26+
configRoot:
27+
{
28+
maxHeight: "90vh",
29+
display: "flex",
30+
flexFlow: "column",
31+
gap: tokens.spacingVerticalM,
32+
width: "100%",
33+
maxWidth: "480px",
34+
borderRadius: tokens.borderRadiusLarge,
35+
boxShadow: tokens.shadow4,
36+
backgroundColor: tokens.colorNeutralBackground2,
37+
padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`,
38+
margin: `${tokens.spacingVerticalL} ${tokens.spacingHorizontalXL}`,
39+
boxSizing: "border-box",
40+
justifySelf: "center",
41+
alignSelf: "center",
42+
overflowY: "auto",
43+
},
44+
switch:
45+
{
46+
margin: `${tokens.spacingVerticalXL} ${tokens.spacingVerticalNone}`,
47+
},
48+
listRoot:
49+
{
50+
width: "100%",
51+
maxWidth: "840px",
52+
alignSelf: "center",
53+
justifySelf: "center",
54+
padding: `${tokens.spacingVerticalXL} ${tokens.spacingHorizontalXL}`,
55+
boxSizing: "border-box",
56+
overflowY: "auto",
57+
maxHeight: "100%",
58+
},
59+
});

entrypoints/advanced/Page.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import DoubleLabledSwitch from "@/shared/DoubleLabeledSwitch";
2+
import { mergeClasses, Toaster } from "@fluentui/react-components";
3+
import { ReactElement } from "react";
4+
import { useMediaQuery } from "react-responsive";
5+
import PasswordList from "./components/PasswordList";
6+
import { useStyles } from "./Page.styles";
7+
import PassphraseSection from "./sections/PassphraseSection";
8+
import PasswordSection from "./sections/PasswordSection";
9+
10+
export default function Page(): ReactElement
11+
{
12+
const [isPassphrase, setIsPassphrase] = useState<boolean | null>(null);
13+
const [passwords, setPasswords] = useState<string[]>([]);
14+
const isSmall = useMediaQuery({ query: "(max-width: 1000px)" });
15+
16+
const cls = useStyles();
17+
18+
useEffect(() =>
19+
{
20+
advancedPassphraseSelected.getValue().then(setIsPassphrase);
21+
const unwatch = advancedPassphraseSelected.watch(setIsPassphrase);
22+
23+
return () => unwatch();
24+
}, []);
25+
26+
if (isPassphrase === null)
27+
return <></>;
28+
29+
return (
30+
<main className={ mergeClasses(cls.root, isSmall && cls.smallRoot) }>
31+
<PasswordList
32+
passwords={ passwords }
33+
className={ mergeClasses(cls.listRoot, isSmall && cls.hideScroll) } />
34+
35+
<article className={ mergeClasses(cls.configRoot, isSmall && cls.hideScroll) }>
36+
<DoubleLabledSwitch outerRoot={ { className: cls.switch } }
37+
checked={ isPassphrase }
38+
onChange={ (_, e) => advancedPassphraseSelected.setValue(e.checked) }
39+
offLabel={ i18n.t("advanced.password.title") }
40+
onLabel={ i18n.t("advanced.passphrase.title") } />
41+
42+
{ isPassphrase ?
43+
<PassphraseSection onGenerated={ setPasswords } />
44+
:
45+
<PasswordSection onGenerated={ setPasswords } />
46+
}
47+
</article>
48+
<Toaster />
49+
</main>
50+
);
51+
};
52+
53+
export type GeneratorProps =
54+
{
55+
onGenerated: (passwords: string[]) => void;
56+
};
57+
58+
const advancedPassphraseSelected = storage.defineItem<boolean>("sync:AdvancedPassphraseSelected", { fallback: false });
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { makeStyles, tokens } from "@fluentui/react-components";
2+
3+
export const useStyles = makeStyles({
4+
root:
5+
{
6+
display: "flex",
7+
flexDirection: "column",
8+
gap: tokens.spacingVerticalXL,
9+
},
10+
actionRoot:
11+
{
12+
display: "flex",
13+
gap: tokens.spacingHorizontalM,
14+
alignSelf: "center",
15+
},
16+
bulkRoot:
17+
{
18+
display: "grid",
19+
alignItems: "center",
20+
gridTemplateColumns: "24px 24px 56px",
21+
}
22+
});
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { Button, Input, InputOnChangeData, MessageBar, MessageBarBody, MessageBarTitle, Text, Toast, ToastTitle, useToastController } from "@fluentui/react-components";
2+
import { bundleIcon, Key24Regular, Save20Filled, Save20Regular } from "@fluentui/react-icons";
3+
import { PropsWithChildren, ReactElement } from "react";
4+
import { useStyles } from "./GeneratorForm.styles";
5+
6+
export default function GeneratorForm(props: GeneratorFormProps): ReactElement
7+
{
8+
const [passwordCount, private_setPasswordCount] = useState<number | null>(5);
9+
const [error, setError] = useState<string | null>(null);
10+
const toaster = useToastController();
11+
12+
const cls = useStyles();
13+
const SaveIcon = bundleIcon(Save20Filled, Save20Regular);
14+
15+
const setPasswordCount = useCallback((_: any, e: InputOnChangeData) =>
16+
{
17+
const n = parseInt(e.value ?? "1");
18+
private_setPasswordCount(isNaN(n) || n < 1 ? null : Math.min(n, 1000));
19+
}, []);
20+
21+
const onSubmit = useCallback((args: React.FormEvent<HTMLFormElement>) =>
22+
{
23+
args.preventDefault();
24+
25+
try
26+
{
27+
setError(null);
28+
props.onGenerate(passwordCount ?? 1);
29+
}
30+
catch (ex)
31+
{
32+
setError((ex as Error).message);
33+
}
34+
}, [props.onGenerate, passwordCount]);
35+
36+
const onSave = useCallback(async () =>
37+
{
38+
props.onSave();
39+
await browser.storage.sync.set({ AdvancedBulkCount: passwordCount ?? 5 });
40+
41+
toaster.dispatchToast(
42+
<Toast>
43+
<ToastTitle>{ i18n.t("advanced.saved_msg") }</ToastTitle>
44+
</Toast>,
45+
{
46+
intent: "success",
47+
timeout: 1000
48+
}
49+
);
50+
}, [props.onSave, toaster, passwordCount]);
51+
52+
useEffect(() =>
53+
{
54+
browser.storage.sync.get("AdvancedBulkCount").then(({ AdvancedBulkCount }) =>
55+
private_setPasswordCount(AdvancedBulkCount as number ?? 5)
56+
);
57+
}, []);
58+
59+
return (
60+
<form onSubmit={ onSubmit } className={ cls.root }>
61+
{ props.children }
62+
63+
{ error &&
64+
<MessageBar intent="error">
65+
<MessageBarBody>
66+
<MessageBarTitle>{ error }</MessageBarTitle>
67+
</MessageBarBody>
68+
</MessageBar>
69+
}
70+
71+
<div className={ cls.actionRoot }>
72+
<div className={ cls.bulkRoot }>
73+
<Key24Regular />
74+
<Text align="center">x</Text>
75+
<Input value={ passwordCount?.toString() ?? "" } onChange={ setPasswordCount } />
76+
</div>
77+
<Button appearance="primary" type="submit">{ i18n.t("advanced.actions.generate") }</Button>
78+
</div>
79+
80+
<Button appearance="subtle" icon={ <SaveIcon /> } onClick={ onSave }>
81+
{ i18n.t("advanced.actions.save_config") }
82+
</Button>
83+
</form>
84+
);
85+
}
86+
87+
export type GeneratorFormProps = PropsWithChildren &
88+
{
89+
onSave: () => void;
90+
onGenerate: (count: number) => void;
91+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { makeStyles, tokens } from "@fluentui/react-components";
2+
3+
export const useStyles = makeStyles({
4+
root:
5+
{
6+
display: "flex",
7+
flexFlow: "column",
8+
gap: tokens.spacingVerticalS,
9+
},
10+
copyAll:
11+
{
12+
alignSelf: "flex-end",
13+
minHeight: "32px",
14+
},
15+
table:
16+
{
17+
backgroundColor: tokens.colorNeutralBackground2,
18+
borderRadius: "16px",
19+
overflow: "clip",
20+
},
21+
row:
22+
{
23+
"&:last-child":
24+
{
25+
borderBottom: "none",
26+
}
27+
},
28+
cell:
29+
{
30+
padding: `${tokens.spacingVerticalL} ${tokens.spacingHorizontalXL}`,
31+
cursor: "pointer",
32+
},
33+
cellLayout:
34+
{
35+
overflowX: "auto",
36+
},
37+
passwordText:
38+
{
39+
textOverflow: "ellipsis",
40+
whiteSpace: "nowrap",
41+
overflowX: "hidden",
42+
display: "block",
43+
marginRight: "36px",
44+
},
45+
copyIcon:
46+
{
47+
verticalAlign: "middle",
48+
padding: tokens.spacingHorizontalXL,
49+
}
50+
});

0 commit comments

Comments
 (0)