+
+
-
-
+
1">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html
index 2b1df2f588..a2e214b13a 100644
--- a/src/app/vault/vault.component.html
+++ b/src/app/vault/vault.component.html
@@ -37,7 +37,8 @@
(onCancelled)="cancelledAddEdit($event)"
(onShareCipher)="shareCipher($event)"
(onEditCollections)="cipherCollections($event)"
- (onGeneratePassword)="openPasswordGenerator(true)"
+ (onGeneratePassword)="openGenerator(true, true)"
+ (onGenerateUsername)="openGenerator(true, false)"
>
(comp.showSelect = showSelect)
+ (comp) => {
+ comp.showSelect = showSelect;
+ if (showSelect) {
+ comp.type = passwordType ? "password" : "username";
+ if (loginType && cipher.login.hasUris && cipher.login.uris[0].hostname != null) {
+ comp.usernameWebsite = cipher.login.uris[0].hostname;
+ comp.showWebsiteOption = true;
+ }
+ }
+ }
);
this.modal = modal;
- childComponent.onSelected.subscribe((password: string) => {
+ childComponent.onSelected.subscribe((value: string) => {
this.modal.close();
- if (
- this.addEditComponent != null &&
- this.addEditComponent.cipher != null &&
- this.addEditComponent.cipher.type === CipherType.Login &&
- this.addEditComponent.cipher.login != null
- ) {
+ if (loginType) {
this.addEditComponent.markPasswordAsDirty();
- this.addEditComponent.cipher.login.password = password;
+ if (passwordType) {
+ this.addEditComponent.cipher.login.password = value;
+ } else {
+ this.addEditComponent.cipher.login.username = value;
+ }
}
});
diff --git a/src/app/vault/view.component.html b/src/app/vault/view.component.html
index 982a1159a4..3a2b12efb8 100644
--- a/src/app/vault/view.component.html
+++ b/src/app/vault/view.component.html
@@ -47,7 +47,7 @@
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index 0d899c25a3..5c2ed68d30 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -369,6 +369,12 @@
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
},
+ "overwriteUsername": {
+ "message": "Overwrite Username"
+ },
+ "overwriteUsernameConfirmation": {
+ "message": "Are you sure you want to overwrite the current username?"
+ },
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"
@@ -1188,7 +1194,12 @@
"message": "This password was not found in any known data breaches. It should be safe to use."
},
"baseDomain": {
- "message": "Base domain"
+ "message": "Base domain",
+ "description": "Domain name. Ex. website.com"
+ },
+ "domainName": {
+ "message": "Domain Name",
+ "description": "Domain name. Ex. website.com"
},
"host": {
"message": "Host",
@@ -1828,5 +1839,47 @@
"example": "name@example.com"
}
}
+ },
+ "generator": {
+ "message": "Generator"
+ },
+ "whatWouldYouLikeToGenerate": {
+ "message": "What would you like to generate?"
+ },
+ "passwordType": {
+ "message": "Password Type"
+ },
+ "regenerateUsername": {
+ "message": "Regenerate Username"
+ },
+ "generateUsername": {
+ "message": "Generate Username"
+ },
+ "usernameType": {
+ "message": "Username Type"
+ },
+ "plusAddressedEmail": {
+ "message": "Plus Addressed Email"
+ },
+ "plusAddressedEmailDesc": {
+ "message": "Use your email provider's sub-addressing capabilities."
+ },
+ "catchallEmail": {
+ "message": "Catch-all Email"
+ },
+ "catchallEmailDesc": {
+ "message": "Use your domain's configured catch-all inbox."
+ },
+ "random": {
+ "message": "Random"
+ },
+ "randomWord": {
+ "message": "Random Word"
+ },
+ "websiteName": {
+ "message": "Website Name"
+ },
+ "service": {
+ "message": "Service"
}
}
diff --git a/src/main/menu.view.ts b/src/main/menu.view.ts
index 6a45cb9644..e3f53e35ba 100644
--- a/src/main/menu.view.ts
+++ b/src/main/menu.view.ts
@@ -16,7 +16,7 @@ export class ViewMenu implements IMenubarMenu {
return [
this.searchVault,
this.separator,
- this.passwordGenerator,
+ this.generator,
this.passwordHistory,
this.separator,
this.zoomIn,
@@ -54,11 +54,11 @@ export class ViewMenu implements IMenubarMenu {
return { type: "separator" };
}
- private get passwordGenerator(): MenuItemConstructorOptions {
+ private get generator(): MenuItemConstructorOptions {
return {
- id: "passwordGenerator",
- label: this.localize("passwordGenerator"),
- click: () => this.sendMessage("openPasswordGenerator"),
+ id: "generator",
+ label: this.localize("generator"),
+ click: () => this.sendMessage("openGenerator"),
accelerator: "CmdOrCtrl+G",
enabled: !this._isLocked,
};
diff --git a/src/scss/box.scss b/src/scss/box.scss
index a50dd68413..ddb7bccac6 100644
--- a/src/scss/box.scss
+++ b/src/scss/box.scss
@@ -4,15 +4,6 @@
position: relative;
width: 100%;
- .settingsTitle {
- margin: 0 10px 5px 10px;
- display: flex;
-
- @include themify($themes) {
- color: themed("headingColor");
- }
- }
-
.box-header {
margin: 0 10px 5px 10px;
text-transform: uppercase;
@@ -302,7 +293,7 @@
&.box-content-row-slider {
input[type="range"] {
height: 10px;
- width: 110px !important;
+ width: 220px !important;
}
input[type="number"] {
@@ -364,33 +355,7 @@
margin-left: 5px;
.row-btn {
- cursor: pointer;
- padding: 10px 8px;
- background: none;
- border: none;
-
- @include themify($themes) {
- color: themed("boxRowButtonColor");
- }
-
- &:hover,
- &:focus {
- @include themify($themes) {
- color: themed("boxRowButtonHoverColor");
- }
- }
-
- &.disabled {
- @include themify($themes) {
- color: themed("disabledIconColor");
- }
-
- &:hover {
- @include themify($themes) {
- color: themed("disabledIconColor");
- }
- }
- }
+ @extend .icon-btn;
}
&.no-pad .row-btn {
@@ -485,4 +450,36 @@
min-width: 25px;
}
}
+
+ .radio-group {
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ margin-bottom: 5px;
+
+ input {
+ flex-grow: 0;
+ }
+
+ label {
+ margin: 0 0 0 5px;
+ flex-grow: 1;
+ font-size: $font-size-base;
+ display: block;
+ width: 100%;
+
+ @include themify($themes) {
+ color: themed("textColor");
+ }
+ }
+
+ &.align-start {
+ align-items: start;
+ margin-top: 10px;
+
+ label {
+ margin-top: -4px;
+ }
+ }
+ }
}
diff --git a/src/scss/buttons.scss b/src/scss/buttons.scss
index 23df91450d..8ff2d676dc 100644
--- a/src/scss/buttons.scss
+++ b/src/scss/buttons.scss
@@ -115,3 +115,57 @@
}
}
}
+
+.icon-btn {
+ cursor: pointer;
+ padding: 10px 8px;
+ background: none;
+ border: none;
+
+ @include themify($themes) {
+ color: themed("boxRowButtonColor");
+ }
+
+ &.primary {
+ @include themify($themes) {
+ color: themed("buttonPrimaryColor");
+ }
+ }
+
+ &.danger {
+ @include themify($themes) {
+ color: themed("buttonDangerColor");
+ }
+ }
+
+ &:hover,
+ &:focus {
+ @include themify($themes) {
+ color: themed("boxRowButtonHoverColor");
+ }
+
+ &.primary {
+ @include themify($themes) {
+ color: darken(themed("buttonPrimaryColor"), 6%);
+ }
+ }
+
+ &.danger {
+ @include themify($themes) {
+ color: darken(themed("buttonDangerColor"), 6%);
+ }
+ }
+ }
+
+ &.disabled {
+ @include themify($themes) {
+ color: themed("disabledIconColor");
+ }
+
+ &:hover {
+ @include themify($themes) {
+ color: themed("disabledIconColor");
+ }
+ }
+ }
+}
diff --git a/src/scss/misc.scss b/src/scss/misc.scss
index aa38b0f86d..250ecc1973 100644
--- a/src/scss/misc.scss
+++ b/src/scss/misc.scss
@@ -1,6 +1,7 @@
@import "variables.scss";
-small {
+small,
+.small {
font-size: $font-size-small;
}
@@ -173,22 +174,44 @@ p.lead {
}
}
-.password-block {
+.modal-title {
+ margin: 0 10px 5px 10px;
+ text-transform: uppercase;
+ display: flex;
+
+ @include themify($themes) {
+ color: themed("headingColor");
+ }
+}
+
+.generated-block {
font-size: $font-size-large;
font-family: $font-family-monospace;
min-height: 50px;
display: flex;
- flex-wrap: wrap;
align-items: center;
justify-content: center;
- text-align: center;
.modal-body & {
- margin-top: 10px;
+ margin: 10px;
+ }
+
+ .generated-wrapper {
+ text-align: left;
+ width: 100%;
+ }
+
+ .action-buttons {
+ display: flex;
+ align-self: center;
+
+ button {
+ margin-left: 10px;
+ }
}
}
-.password-wrapper {
+.generated-wrapper {
word-break: break-all;
white-space: pre-wrap;
min-width: 0;