diff --git a/keepassxc-browser/_locales/en/messages.json b/keepassxc-browser/_locales/en/messages.json
index 9bd0fcf..59321a6 100644
--- a/keepassxc-browser/_locales/en/messages.json
+++ b/keepassxc-browser/_locales/en/messages.json
@@ -23,6 +23,10 @@
"message": "Save credentials",
"description": "Save credentials using the extension popup icon."
},
+ "contextMenuShowPasswordGenerator": {
+ "message": "Show password generator",
+ "description": "Show password generator text."
+ },
"rememberCredentialsPopup": {
"message": "Create or modify the credentials by clicking on the extension icon.",
"description": "Notification text when saving credentials from the context menu."
@@ -95,6 +99,10 @@
"message": "No logins found.",
"description": "No logins found."
},
+ "passwordGeneratorIcon": {
+ "message": "Password generator icon",
+ "description": "Alt attribute text of the password generator icon."
+ },
"passwordGeneratorPlaceholder": {
"message": "Generated password",
"description": "Input field placeholder for generated password."
@@ -183,6 +191,10 @@
"message": "Please confirm your selection or choose more fields as String fields.",
"description": "Confirm a selection text when choosing custom login fields which contains string fields."
},
+ "defineKeyboardText": {
+ "message": "You can also use the numbers to choose the input fields from keyboard.",
+ "description": "Help text when choosing custom login fields."
+ },
"username": {
"message": "Username",
"description": "General text for username."
@@ -671,6 +683,10 @@
"message": "No saved custom login fields found.",
"description": "Shown when no saved custom credentials are saved."
},
+ "optionsCustomFieldsTableCaption": {
+ "message": "You can manage saved custom login fields using the table below.",
+ "description": "Table caption of Custom login fields page."
+ },
"optionsCustomFieldsTabHelpTextFirst": {
"message": "If KeePassXC-Browser detects the wrong login fields, you are able to specify the correct fields yourself.",
"description": "Saved custom login fields info text, first part."
@@ -679,10 +695,6 @@
"message": "Go to the page and click on the KeePassXC-Browser icon, then select ",
"description": "Saved custom login fields info text, second part."
},
- "optionsCustomFieldsTabHelpTextThird": {
- "message": "On this page you can manage saved custom login fields.",
- "description": "Saved custom login fields info text, third part."
- },
"optionsCustomFieldsRemove": {
"message": "Remove saved custom login fields?",
"description": "Confirmation text when removing saved custom login fields."
@@ -720,7 +732,7 @@
"description": "Site preferences info text, fourth part."
},
"optionsSitePreferencesManualAddText": {
- "message": "Add URL manually:",
+ "message": "Add URL manually",
"description": "Label for adding site manually on Site preferences tab."
},
"optionsSitePreferencesConfirmation": {
@@ -731,6 +743,14 @@
"message": "KeePassXC-Browser will enable all features for this site and remove username-only detection.",
"description": "Part of confirmation text when removing site preferences."
},
+ "optionsSitePreferencesTableCaption": {
+ "message": "You can manage saved site preferences using the table below.",
+ "description": "Table caption of Site Preferences page."
+ },
+ "optionsSitePreferencesSelect": {
+ "message": "Option to ignore extension features for the page.",
+ "description": "Title text of select element in Site Preferences."
+ },
"optionsAboutChrome": {
"message": "Visit KeePassXC-Browser in the Chrome Web Store.",
"description": "About page link to Chrome Web Store."
@@ -752,11 +772,43 @@
"description": "About page text of KeePassXC version."
},
"optionsAboutContributors": {
- "message": "Contributors:",
+ "message": "Contributors",
"description": "About page text of contributors."
},
"optionsAboutLicenses": {
- "message": "Licenses:",
+ "message": "Licenses",
"description": "About page text of licenses."
+ },
+ "optionsAboutReportBugs": {
+ "message": "Report bugs",
+ "description": "About page text of reporting bugs."
+ },
+ "optionsAboutCreateNewIssue": {
+ "message": "Create new issue on GitHub",
+ "description": "Link text for creating a new issue."
+ },
+ "optionsAboutDebugInfo": {
+ "message": "The following debug info can be used",
+ "description": "Debug info text."
+ },
+ "optionsErrorInvalidValue": {
+ "message": "Invalid value. Please check the input.",
+ "description": "Error shown when input field has an incorrect value."
+ },
+ "optionsErrorInvalidURL": {
+ "message": "Invalid URL. Please check the input.",
+ "description": "Error shown when input field has an incorrect URL."
+ },
+ "optionsErrorValueExists": {
+ "message": "The value already exists in the list.",
+ "description": "Error shown when trying to add a duplicate value to the list."
+ },
+ "openNewTab": {
+ "message": "Opens a new tab",
+ "description": "Title attribute text."
+ },
+ "httpAuthDialog": {
+ "message": "HTTP Basic Authentication dialog",
+ "description": "Options page HTTP Basic Auth dialog text"
}
}
diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js
index f4797c5..c603f9f 100644
--- a/keepassxc-browser/background/init.js
+++ b/keepassxc-browser/background/init.js
@@ -81,11 +81,12 @@ browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
browser.runtime.onMessage.addListener(kpxcEvent.onMessage);
const contextMenuItems = [
- {title: tr('contextMenuFillUsernameAndPassword'), action: 'fill_username_password'},
- {title: tr('contextMenuFillPassword'), action: 'fill_password'},
- {title: tr('contextMenuFillTOTP'), action: 'fill_totp'},
- {title: tr('contextMenuShowPasswordGeneratorIcons'), action: 'activate_password_generator'},
- {title: tr('contextMenuSaveCredentials'), action: 'remember_credentials'}
+ { title: tr('contextMenuFillUsernameAndPassword'), action: 'fill_username_password' },
+ { title: tr('contextMenuFillPassword'), action: 'fill_password' },
+ { title: tr('contextMenuFillTOTP'), action: 'fill_totp' },
+ { title: tr('contextMenuShowPasswordGeneratorIcons'), action: 'activate_password_generator' },
+ { title: tr('contextMenuSaveCredentials'), action: 'remember_credentials' },
+ { title: tr('contextMenuShowPasswordGenerator'), action: 'show_password_generator' }
];
const menuContexts = ['editable'];
diff --git a/keepassxc-browser/keepassxc-browser.css b/keepassxc-browser/keepassxc-browser.css
index 9c3b0f7..6e55f77 100644
--- a/keepassxc-browser/keepassxc-browser.css
+++ b/keepassxc-browser/keepassxc-browser.css
@@ -117,15 +117,15 @@ input.genpw-text {
}
.b2c-modal-backdrop:after {
- content:'';
+ content: '';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000000;
- opacity: 0.8;
- filter: alpha(opacity=80);
+ opacity: 0.5;
+ filter: alpha(opacity=50);
}
#b2c-cipDefine-fields {
@@ -142,7 +142,7 @@ input.genpw-text {
left: 150px;
text-align: left;
cursor: pointer;
- background-color:rgba(255,255,255,0.3);
+ background-color: rgba(0,0,0,0.8);
font-size: 15px;
}
@@ -168,12 +168,28 @@ input.genpw-text {
margin-bottom: 3px;
}
+#b2c-keyboardHelp {
+ font-size: 0.75em;
+}
+
+#b2c-keyboardHelp kbd {
+ background-color: #eee;
+ border-radius: 3px;
+ border: 1px solid #b4b4b4;
+ color: #333;
+ display: inline-block;
+ line-height: 1;
+ padding: 2px 4px;
+ white-space: nowrap;
+}
+
.b2c-fixed-field {
position: absolute;
border: 2px solid #efefef;
+ color: #fff;
cursor: pointer;
z-index: 2147483646;
- text-align: left;
+ text-align: center;
font-weight: bold;
background-color:rgba(239,239,239,0.4);
}
diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js
index 26f41e3..d09b537 100755
--- a/keepassxc-browser/keepassxc-browser.js
+++ b/keepassxc-browser/keepassxc-browser.js
@@ -37,21 +37,21 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) {
cip.setValueWithChange(cip.u, cip.credentials[req.id].login);
combination = cipFields.getCombination('username', cip.u);
browser.runtime.sendMessage({
- action: 'page_set_login_id', args: [req.id]
+ action: 'page_set_login_id', args: [ req.id ]
});
cip.u.focus();
}
if (cip.p) {
cip.setValueWithChange(cip.p, cip.credentials[req.id].password);
browser.runtime.sendMessage({
- action: 'page_set_login_id', args: [req.id]
+ action: 'page_set_login_id', args: [ req.id ]
});
combination = cipFields.getCombination('password', cip.p);
}
let list = [];
if (cip.fillInStringFields(combination.fields, cip.credentials[req.id].stringFields, list)) {
- cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]});
+ cipForm.destroy(false, { 'password': list.list[0], 'username': list.list[1] });
}
}
} else if (req.action === 'fill_username_password') {
@@ -89,9 +89,10 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) {
});
} else if (req.action === 'ignore-site') {
cip.ignoreSite(req.args);
- }
- else if (req.action === 'check_database_hash' && 'hash' in req) {
+ } else if (req.action === 'check_database_hash' && 'hash' in req) {
cip.detectDatabaseChange(req.hash);
+ } else if (req.action === 'show_password_generator') {
+ cipPassword.showDialog();
}
}
});
@@ -108,7 +109,7 @@ cipAutocomplete.init = function(field) {
}
const acMenu = jQuery('#kpxc-ac-menu');
- if (acMenu.length == 0) {
+ if (acMenu.length === 0) {
jQuery('
').appendTo('body');
}
@@ -240,6 +241,7 @@ cipPassword.createDialog = function() {
.attr('type', 'text')
.attr('aria-describedby', 'cip-genpw-quality')
.attr('placeholder', tr('passwordGeneratorPlaceholder'))
+ .attr('tabindex', -1)
.addClass('genpw-text ui-widget-content ui-corner-all')
.on('change keypress paste textInput input', function() {
jQuery('#cip-genpw-btn-clipboard:first').removeClass('btn-success');
@@ -369,6 +371,7 @@ cipPassword.createIcon = function(field) {
.addClass('cip-genpw-icon')
.addClass($className)
.attr('title', tr('passwordGeneratorGenerateText'))
+ .attr('alt', tr('passwordGeneratorIcon'))
.css('z-index', '9999')
.css('width', $size)
.css('height', $size)
@@ -408,6 +411,10 @@ cipPassword.createIcon = function(field) {
jQuery('body').append($icon);
};
+cipPassword.showDialog = function() {
+ $('.cip-genpw-icon').click();
+};
+
cipPassword.setIconPosition = function($icon, $field) {
$icon.css('top', $field.offset().top + $icon.data('offset') + 1)
.css('left', $field.offset().left + $field.outerWidth() - $icon.data('size') - $icon.data('offset'));
@@ -556,6 +563,7 @@ cipDefine.selection = {
fields: []
};
cipDefine.eventFieldClick = null;
+cipDefine.keyDown = null;
cipDefine.init = function() {
const $backdrop = jQuery('').attr('id', 'b2c-backdrop').addClass('b2c-modal-backdrop');
@@ -575,6 +583,14 @@ cipDefine.init = function() {
cipDefine.resetSelection();
cipDefine.prepareStep1();
cipDefine.markAllUsernameFields($chooser);
+
+ document.addEventListener('keydown', cipDefine.keyDown);
+};
+
+cipDefine.close = function() {
+ $('div#b2c-backdrop').remove();
+ $('div#b2c-cipDefine-fields').remove();
+ document.removeEventListener('keydown', cipDefine.keyDown);
};
cipDefine.initDescription = function() {
@@ -583,85 +599,44 @@ cipDefine.initDescription = function() {
$description.append($h1);
const $help = jQuery('
').addClass('b2c-chooser-help').attr('id', 'b2c-help');
$description.append($help);
+ const $keyboardHelp = jQuery('
').addClass('b2c-chooser-help').attr('id', 'b2c-keyboardHelp');
+ $description.append($keyboardHelp);
+
+ // Show keyboard shortcuts help text
+ jQuery('div#b2c-keyboardHelp').text(`${tr('optionsKeyboardShortcutsHeader')}:`).css('margin-bottom', '5px');
+ jQuery('div#b2c-keyboardHelp').append($('
Escape')).append(' ' + tr('defineDismiss'));
+ jQuery('div#b2c-keyboardHelp').append($('
S')).append(' ' + tr('defineSkip'));
+ jQuery('div#b2c-keyboardHelp').append($('
A')).append(' ' + tr('defineAgain'));
+ jQuery('div#b2c-keyboardHelp').append($('
C')).append(' ' + tr('defineConfirm'));
+ jQuery('div#b2c-keyboardHelp').append($('
M')).append(' ' + tr('defineMore'));
+ jQuery('div#b2c-keyboardHelp').append($('
D')).append(' ' + tr('defineDiscard'));
const $btnDismiss = jQuery('