mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Merge pull request #617 from keepassxreboot/fix/icon_handling_refactor
Fix handling multiple icons
This commit is contained in:
commit
b3ebe63c92
5 changed files with 203 additions and 188 deletions
|
|
@ -60,7 +60,7 @@ browser.runtime.onMessage.addListener(async function(req, sender) {
|
|||
kpxc.settings = response;
|
||||
kpxc.initCredentialFields(true);
|
||||
} else if (req.action === 'show_password_generator') {
|
||||
kpxcPassword.trigger();
|
||||
kpxcPasswordDialog.trigger();
|
||||
} else if (req.action === 'add_username_only_option') {
|
||||
kpxc.addToSitePreferences();
|
||||
}
|
||||
|
|
@ -448,7 +448,7 @@ kpxcFields.getUsernameField = function(passwordId, checkDisabled) {
|
|||
}
|
||||
|
||||
if (kpxc.settings.showLoginFormIcon) {
|
||||
kpxcUsernameField.initField(usernameField);
|
||||
kpxcUsernameFields.newIcon(usernameField);
|
||||
}
|
||||
usernameField = i;
|
||||
}
|
||||
|
|
@ -506,8 +506,7 @@ kpxcFields.getPasswordField = function(usernameId, checkDisabled) {
|
|||
passwordField = null;
|
||||
}
|
||||
|
||||
kpxcPassword.init(kpxc.settings.usePasswordGeneratorIcons);
|
||||
kpxcPassword.initField(passwordField);
|
||||
kpxcPasswordIcons.newIcon(kpxc.settings.usePasswordGeneratorIcons, passwordField);
|
||||
} else {
|
||||
// Search all inputs on page
|
||||
const inputs = kpxcFields.getAllFields();
|
||||
|
|
@ -564,7 +563,7 @@ kpxcFields.prepareCombinations = async function(combinations) {
|
|||
});
|
||||
|
||||
if (kpxc.settings.showLoginFormIcon) {
|
||||
kpxcUsernameField.initField(usernameField, res.databaseClosed);
|
||||
kpxcUsernameFields.newIcon(usernameField, res.databaseClosed);
|
||||
}
|
||||
|
||||
// Initialize form-submit for remembering credentials
|
||||
|
|
@ -856,7 +855,7 @@ kpxc.clearAllFromPage = function() {
|
|||
// Switch credentials if database is changed or closed
|
||||
kpxc.detectDatabaseChange = async function(response) {
|
||||
kpxc.clearAllFromPage();
|
||||
kpxcUsernameField.switchIcon(true);
|
||||
kpxcUsernameFields.switchIcon(true);
|
||||
|
||||
if (document.visibilityState !== 'hidden') {
|
||||
if (response.new !== '' && response.new !== response.old) {
|
||||
|
|
@ -866,7 +865,7 @@ kpxc.detectDatabaseChange = async function(response) {
|
|||
});
|
||||
kpxc.settings = settings;
|
||||
await kpxc.initCredentialFields(true);
|
||||
kpxcUsernameField.switchIcon(false); // Unlocked
|
||||
kpxcUsernameFields.switchIcon(false); // Unlocked
|
||||
|
||||
// If user has requested a manual fill through context menu the actual credential filling
|
||||
// is handled here when the opened database has been regognized. It's not a pretty hack.
|
||||
|
|
@ -963,11 +962,9 @@ kpxc.initCredentialFields = async function(forceCall) {
|
|||
};
|
||||
|
||||
kpxc.initPasswordGenerator = function(inputs) {
|
||||
kpxcPassword.init(kpxc.settings.usePasswordGeneratorIcons);
|
||||
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
if (inputs[i] && inputs[i].getLowerCaseAttribute('type') === 'password') {
|
||||
kpxcPassword.initField(inputs[i], inputs, i);
|
||||
kpxcPasswordIcons.newIcon(kpxc.settings.usePasswordGeneratorIcons, inputs[i], inputs, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1783,7 +1780,7 @@ kpxcEvents.triggerActivatedTab = async function() {
|
|||
|
||||
// Update username field lock state
|
||||
const state = await browser.runtime.sendMessage({ action: 'check_database_hash' });
|
||||
kpxcUsernameField.switchIcon(state === '');
|
||||
kpxcUsernameFields.switchIcon(state === '');
|
||||
|
||||
// initCredentialFields calls also "retrieve_credentials", to prevent it
|
||||
// check of init() was already called
|
||||
|
|
|
|||
|
|
@ -1,36 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
const kpxcPassword = {};
|
||||
kpxcPassword.created = false;
|
||||
kpxcPassword.icon = null;
|
||||
kpxcPassword.inputField = null;
|
||||
kpxcPassword.selected = null;
|
||||
kpxcPassword.startPosX = 0;
|
||||
kpxcPassword.startPosY = 0;
|
||||
kpxcPassword.diffX = 0;
|
||||
kpxcPassword.diffY = 0;
|
||||
kpxcPassword.dialog = null;
|
||||
kpxcPassword.titleBar = null;
|
||||
kpxcPassword.useIcons = false;
|
||||
const kpxcPasswordIcons = {};
|
||||
kpxcPasswordIcons.icons = [];
|
||||
|
||||
try {
|
||||
kpxcPassword.observer = new IntersectionObserver((entries) => {
|
||||
kpxcUI.updateFromIntersectionObserver(kpxcPassword, entries);
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
kpxcPassword.init = function(useIcons) {
|
||||
kpxcPassword.useIcons = useIcons;
|
||||
if ('initPasswordGenerator' in _called) {
|
||||
return;
|
||||
}
|
||||
|
||||
_called.initPasswordGenerator = true;
|
||||
kpxcPasswordIcons.newIcon = function(field, databaseClosed = true) {
|
||||
kpxcPasswordIcons.icons.push(new PasswordIcon(field, databaseClosed));
|
||||
};
|
||||
|
||||
kpxcPassword.initField = function(field, inputs, pos) {
|
||||
|
||||
class PasswordIcon extends Icon {
|
||||
constructor(useIcons, field, inputs, pos) {
|
||||
super();
|
||||
this.useIcons = useIcons;
|
||||
|
||||
this.initField(field, inputs, pos);
|
||||
kpxcUI.monitorIconPosition(this);
|
||||
}
|
||||
};
|
||||
|
||||
PasswordIcon.prototype.initField = function(field, inputs, pos) {
|
||||
if (!field) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -41,15 +29,15 @@ kpxcPassword.initField = function(field, inputs, pos) {
|
|||
|
||||
field.setAttribute('kpxc-password-generator', true);
|
||||
|
||||
if (kpxcPassword.useIcons) {
|
||||
if (this.useIcons) {
|
||||
// Observer the visibility
|
||||
if (kpxcPassword.observer) {
|
||||
kpxcPassword.observer.observe(field);
|
||||
if (this.observer) {
|
||||
this.observer.observe(field);
|
||||
}
|
||||
kpxcPassword.createIcon(field);
|
||||
this.createIcon(field);
|
||||
}
|
||||
|
||||
kpxcPassword.inputField = field;
|
||||
this.inputField = field;
|
||||
|
||||
let found = false;
|
||||
if (inputs) {
|
||||
|
|
@ -66,7 +54,7 @@ kpxcPassword.initField = function(field, inputs, pos) {
|
|||
field.setAttribute('kpxc-pwgen-next-field-exists', found);
|
||||
};
|
||||
|
||||
kpxcPassword.createIcon = function(field) {
|
||||
PasswordIcon.prototype.createIcon = function(field) {
|
||||
const className = (isFirefox() ? 'key-moz' : 'key');
|
||||
const size = (field.offsetHeight > 28) ? 24 : 16;
|
||||
let offset = Math.floor((field.offsetHeight - size) / 3);
|
||||
|
|
@ -90,15 +78,27 @@ kpxcPassword.createIcon = function(field) {
|
|||
}
|
||||
|
||||
e.preventDefault();
|
||||
kpxcPassword.showDialog(field, icon);
|
||||
kpxcPasswordDialog.showDialog(field, icon);
|
||||
});
|
||||
|
||||
kpxcUI.setIconPosition(icon, field);
|
||||
kpxcPassword.icon = icon;
|
||||
this.icon = icon;
|
||||
document.body.appendChild(icon);
|
||||
};
|
||||
|
||||
kpxcPassword.removeIcon = function(field) {
|
||||
|
||||
const kpxcPasswordDialog = {};
|
||||
kpxcPasswordDialog.created = false;
|
||||
kpxcPasswordDialog.icon = null;
|
||||
kpxcPasswordDialog.selected = null;
|
||||
kpxcPasswordDialog.startPosX = 0;
|
||||
kpxcPasswordDialog.startPosY = 0;
|
||||
kpxcPasswordDialog.diffX = 0;
|
||||
kpxcPasswordDialog.diffY = 0;
|
||||
kpxcPasswordDialog.dialog = null;
|
||||
kpxcPasswordDialog.titleBar = null;
|
||||
|
||||
kpxcPasswordDialog.removeIcon = function(field) {
|
||||
if (field.getAttribute('kpxc-password-generator')) {
|
||||
const pwgenIcons = document.querySelectorAll('.kpxc-pwgen-icon');
|
||||
for (const i of pwgenIcons) {
|
||||
|
|
@ -109,16 +109,16 @@ kpxcPassword.removeIcon = function(field) {
|
|||
}
|
||||
};
|
||||
|
||||
kpxcPassword.createDialog = function() {
|
||||
if (kpxcPassword.created) {
|
||||
kpxcPasswordDialog.createDialog = function() {
|
||||
if (kpxcPasswordDialog.created) {
|
||||
// If database is open again, generate a new password right away
|
||||
const input = $('.kpxc-pwgen-input');
|
||||
if (input.style.display === 'none') {
|
||||
kpxcPassword.generate();
|
||||
kpxcPasswordDialog.generate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
kpxcPassword.created = true;
|
||||
kpxcPasswordDialog.created = true;
|
||||
|
||||
const wrapper = kpxcUI.createElement('div', 'kpxc');
|
||||
const dialog = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-dialog');
|
||||
|
|
@ -129,7 +129,7 @@ kpxcPassword.createDialog = function() {
|
|||
return;
|
||||
}
|
||||
|
||||
kpxcPassword.openDialog();
|
||||
kpxcPasswordDialog.openDialog();
|
||||
});
|
||||
titleBar.append(closeButton);
|
||||
|
||||
|
|
@ -144,16 +144,16 @@ kpxcPassword.createDialog = function() {
|
|||
const fillButton = kpxcUI.createElement('button', 'kpxc-button kpxc-green-button', { 'id': 'kpxc-pwgen-btn-fill' }, tr('passwordGeneratorFill'));
|
||||
|
||||
generateButton.addEventListener('click', function(e) {
|
||||
kpxcPassword.generate(e);
|
||||
kpxcPasswordDialog.generate(e);
|
||||
});
|
||||
|
||||
fillButton.addEventListener('click', function(e) {
|
||||
kpxcPassword.fill(e);
|
||||
kpxcPassword.openDialog();
|
||||
kpxcPasswordDialog.fill(e);
|
||||
kpxcPasswordDialog.openDialog();
|
||||
});
|
||||
|
||||
copyButton.addEventListener('click', function(e) {
|
||||
kpxcPassword.copy(e);
|
||||
kpxcPasswordDialog.copy(e);
|
||||
});
|
||||
|
||||
buttonsRow.appendMultiple(generateButton, copyButton, fillButton);
|
||||
|
|
@ -172,60 +172,60 @@ kpxcPassword.createDialog = function() {
|
|||
|
||||
document.body.append(wrapper);
|
||||
|
||||
kpxcPassword.dialog = dialog;
|
||||
kpxcPassword.titleBar = titleBar;
|
||||
kpxcPassword.titleBar.addEventListener('mousedown', function(e) {
|
||||
kpxcPassword.mouseDown(e);
|
||||
kpxcPasswordDialog.dialog = dialog;
|
||||
kpxcPasswordDialog.titleBar = titleBar;
|
||||
kpxcPasswordDialog.titleBar.addEventListener('mousedown', function(e) {
|
||||
kpxcPasswordDialog.mouseDown(e);
|
||||
});
|
||||
|
||||
kpxcPassword.generate();
|
||||
kpxcPasswordDialog.generate();
|
||||
};
|
||||
|
||||
kpxcPassword.mouseDown = function(e) {
|
||||
kpxcPassword.selected = kpxcPassword.titleBar;
|
||||
kpxcPassword.startPosX = e.clientX;
|
||||
kpxcPassword.startPosY = e.clientY;
|
||||
kpxcPassword.diffX = kpxcPassword.startPosX - kpxcPassword.dialog.offsetLeft;
|
||||
kpxcPassword.diffY = kpxcPassword.startPosY - kpxcPassword.dialog.offsetTop;
|
||||
kpxcPasswordDialog.mouseDown = function(e) {
|
||||
kpxcPasswordDialog.selected = kpxcPasswordDialog.titleBar;
|
||||
kpxcPasswordDialog.startPosX = e.clientX;
|
||||
kpxcPasswordDialog.startPosY = e.clientY;
|
||||
kpxcPasswordDialog.diffX = kpxcPasswordDialog.startPosX - kpxcPasswordDialog.dialog.offsetLeft;
|
||||
kpxcPasswordDialog.diffY = kpxcPasswordDialog.startPosY - kpxcPasswordDialog.dialog.offsetTop;
|
||||
return false;
|
||||
};
|
||||
|
||||
kpxcPassword.openDialog = function() {
|
||||
if (kpxcPassword.dialog.style.display === '' || kpxcPassword.dialog.style.display === 'none') {
|
||||
kpxcPassword.dialog.style.display = 'block';
|
||||
kpxcPasswordDialog.openDialog = function() {
|
||||
if (kpxcPasswordDialog.dialog.style.display === '' || kpxcPasswordDialog.dialog.style.display === 'none') {
|
||||
kpxcPasswordDialog.dialog.style.display = 'block';
|
||||
} else {
|
||||
kpxcPassword.dialog.style.display = 'none';
|
||||
kpxcPasswordDialog.dialog.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
kpxcPassword.trigger = function() {
|
||||
kpxcPassword.showDialog(kpxcPassword.inputField || document.activeElement, kpxcPassword.icon);
|
||||
kpxcPasswordDialog.trigger = function() {
|
||||
kpxcPasswordDialog.showDialog(document.activeElement, kpxcPasswordDialog.icon);
|
||||
};
|
||||
|
||||
kpxcPassword.showDialog = function(field, icon) {
|
||||
kpxcPasswordDialog.showDialog = function(field, icon) {
|
||||
if (!kpxcFields.isVisible(field)) {
|
||||
document.body.removeChild(icon);
|
||||
field.removeAttribute('kpxc-password-generator');
|
||||
return;
|
||||
}
|
||||
|
||||
kpxcPassword.createDialog();
|
||||
kpxcPassword.openDialog();
|
||||
kpxcPasswordDialog.createDialog();
|
||||
kpxcPasswordDialog.openDialog();
|
||||
|
||||
// Adjust the dialog location
|
||||
if (kpxcPassword.dialog) {
|
||||
if (kpxcPasswordDialog.dialog) {
|
||||
if (icon) {
|
||||
kpxcPassword.dialog.style.top = Pixels(icon.offsetTop + icon.offsetHeight);
|
||||
kpxcPassword.dialog.style.left = icon.style.left;
|
||||
kpxcPasswordDialog.dialog.style.top = Pixels(icon.offsetTop + icon.offsetHeight);
|
||||
kpxcPasswordDialog.dialog.style.left = icon.style.left;
|
||||
} else {
|
||||
const rect = document.activeElement.getBoundingClientRect();
|
||||
kpxcPassword.dialog.style.top = Pixels(rect.top + rect.height);
|
||||
kpxcPassword.dialog.style.left = Pixels(rect.left);
|
||||
kpxcPasswordDialog.dialog.style.top = Pixels(rect.top + rect.height);
|
||||
kpxcPasswordDialog.dialog.style.left = Pixels(rect.left);
|
||||
}
|
||||
|
||||
kpxcPassword.dialog.setAttribute('kpxc-pwgen-field-id', field.getAttribute('data-kpxc-id'));
|
||||
kpxcPassword.dialog.setAttribute('kpxc-pwgen-next-field-id', field.getAttribute('kpxc-pwgen-next-field-id'));
|
||||
kpxcPassword.dialog.setAttribute('kpxc-pwgen-next-is-password-field', field.getAttribute('kpxc-pwgen-next-is-password-field'));
|
||||
kpxcPasswordDialog.dialog.setAttribute('kpxc-pwgen-field-id', field.getAttribute('data-kpxc-id'));
|
||||
kpxcPasswordDialog.dialog.setAttribute('kpxc-pwgen-next-field-id', field.getAttribute('kpxc-pwgen-next-field-id'));
|
||||
kpxcPasswordDialog.dialog.setAttribute('kpxc-pwgen-next-is-password-field', field.getAttribute('kpxc-pwgen-next-is-password-field'));
|
||||
|
||||
const fieldExists = Boolean(field.getAttribute('kpxc-pwgen-next-field-exists'));
|
||||
const checkbox = $('.kpxc-pwgen-checkbox');
|
||||
|
|
@ -240,7 +240,7 @@ kpxcPassword.showDialog = function(field, icon) {
|
|||
}
|
||||
};
|
||||
|
||||
kpxcPassword.generate = async function(e) {
|
||||
kpxcPasswordDialog.generate = async function(e) {
|
||||
// This function can be also called from non-events
|
||||
if (e) {
|
||||
if (!e.isTrusted) {
|
||||
|
|
@ -254,16 +254,16 @@ kpxcPassword.generate = async function(e) {
|
|||
}));
|
||||
};
|
||||
|
||||
kpxcPassword.copy = function(e) {
|
||||
kpxcPasswordDialog.copy = function(e) {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
kpxcPassword.copyPasswordToClipboard();
|
||||
kpxcPasswordDialog.copyPasswordToClipboard();
|
||||
};
|
||||
|
||||
kpxcPassword.fill = function(e) {
|
||||
kpxcPasswordDialog.fill = function(e) {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ kpxcPassword.fill = function(e) {
|
|||
e.preventDefault();
|
||||
|
||||
// Use the active input field
|
||||
const field = _f(kpxcPassword.dialog.getAttribute('kpxc-pwgen-field-id'));
|
||||
const field = _f(kpxcPasswordDialog.dialog.getAttribute('kpxc-pwgen-field-id'));
|
||||
if (field) {
|
||||
const password = $('.kpxc-pwgen-input');
|
||||
if (field.getAttribute('maxlength')) {
|
||||
|
|
@ -296,7 +296,7 @@ kpxcPassword.fill = function(e) {
|
|||
}
|
||||
};
|
||||
|
||||
kpxcPassword.copyPasswordToClipboard = function() {
|
||||
kpxcPasswordDialog.copyPasswordToClipboard = function() {
|
||||
$('.kpxc-pwgen-input').select();
|
||||
try {
|
||||
return document.execCommand('copy');
|
||||
|
|
@ -344,13 +344,3 @@ const disableButtons = function() {
|
|||
$('#kpxc-pwgen-btn-copy').style.display = 'none';
|
||||
$('#kpxc-pwgen-btn-fill').style.display = 'none';
|
||||
};
|
||||
|
||||
// Handle icon position on window resize
|
||||
window.addEventListener('resize', function(e) {
|
||||
kpxcUI.updateIconPosition(kpxcPassword);
|
||||
});
|
||||
|
||||
// Handle icon position on scroll
|
||||
window.addEventListener('scroll', function(e) {
|
||||
kpxcUI.updateIconPosition(kpxcPassword);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,6 +10,19 @@ const Pixels = function(value) {
|
|||
return String(value) + 'px';
|
||||
};
|
||||
|
||||
// Basic icon class
|
||||
class Icon {
|
||||
constructor() {
|
||||
try {
|
||||
this.observer = new IntersectionObserver((entries) => {
|
||||
kpxcUI.updateFromIntersectionObserver(this, entries);
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const kpxcUI = {};
|
||||
|
||||
// Wrapper for creating elements
|
||||
|
|
@ -36,6 +49,18 @@ kpxcUI.createElement = function(type, classes, attributes, textContent) {
|
|||
return element;
|
||||
};
|
||||
|
||||
kpxcUI.monitorIconPosition = function(iconClass) {
|
||||
// Handle icon position on resize
|
||||
window.addEventListener('resize', function(e) {
|
||||
kpxcUI.updateIconPosition(iconClass);
|
||||
});
|
||||
|
||||
// Handle icon position on scroll
|
||||
window.addEventListener('scroll', function(e) {
|
||||
kpxcUI.updateIconPosition(iconClass);
|
||||
});
|
||||
};
|
||||
|
||||
kpxcUI.updateIconPosition = function(iconClass) {
|
||||
if (iconClass.inputField && iconClass.icon) {
|
||||
kpxcUI.setIconPosition(iconClass.icon, iconClass.inputField);
|
||||
|
|
@ -62,6 +87,7 @@ kpxcUI.setIconPosition = function(icon, field) {
|
|||
kpxcUI.updateFromIntersectionObserver = function(iconClass, entries) {
|
||||
for (const entry of entries) {
|
||||
const rect = DOMRectToArray(entry.boundingClientRect);
|
||||
const temp = entry.target.closest('.kpxc-username-icon');
|
||||
|
||||
if ((entry.intersectionRatio === 0 && !entry.isIntersecting) || (rect.some(x => x < -10))) {
|
||||
iconClass.icon.style.display = 'none';
|
||||
|
|
@ -115,13 +141,13 @@ const DOMRectToArray = function(domRect) {
|
|||
|
||||
// Enables dragging
|
||||
document.addEventListener('mousemove', function(e) {
|
||||
if (kpxcPassword.selected === kpxcPassword.titleBar) {
|
||||
const xPos = e.clientX - kpxcPassword.diffX;
|
||||
const yPos = e.clientY - kpxcPassword.diffY;
|
||||
if (kpxcPasswordDialog.selected === kpxcPasswordDialog.titleBar) {
|
||||
const xPos = e.clientX - kpxcPasswordDialog.diffX;
|
||||
const yPos = e.clientY - kpxcPasswordDialog.diffY;
|
||||
|
||||
if (kpxcPassword.selected !== null) {
|
||||
kpxcPassword.dialog.style.left = Pixels(xPos);
|
||||
kpxcPassword.dialog.style.top = Pixels(yPos);
|
||||
if (kpxcPasswordDialog.selected !== null) {
|
||||
kpxcPasswordDialog.dialog.style.left = Pixels(xPos);
|
||||
kpxcPasswordDialog.dialog.style.top = Pixels(yPos);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +163,7 @@ document.addEventListener('mousemove', function(e) {
|
|||
});
|
||||
|
||||
document.addEventListener('mouseup', function() {
|
||||
kpxcPassword.selected = null;
|
||||
kpxcPasswordDialog.selected = null;
|
||||
kpxcDefine.selected = null;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
const kpxcUsernameField = {};
|
||||
kpxcUsernameField.icon = null;
|
||||
kpxcUsernameField.inputField = null;
|
||||
const kpxcUsernameFields = {};
|
||||
kpxcUsernameFields.icons = [];
|
||||
|
||||
try {
|
||||
kpxcUsernameField.observer = new IntersectionObserver((entries) => {
|
||||
kpxcUI.updateFromIntersectionObserver(kpxcUsernameField, entries);
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
kpxcUsernameFields.newIcon = function(field, databaseClosed = true) {
|
||||
kpxcUsernameFields.icons.push(new UsernameFieldIcon(field, databaseClosed));
|
||||
};
|
||||
|
||||
kpxcUsernameField.initField = function(field, databaseClosed = true) {
|
||||
kpxcUsernameFields.switchIcon = function(locked) {
|
||||
kpxcUsernameFields.icons.forEach(u => u.switchIcon(locked));
|
||||
};
|
||||
|
||||
|
||||
class UsernameFieldIcon extends Icon {
|
||||
constructor(field, databaseClosed = true) {
|
||||
super();
|
||||
this.icon = null;
|
||||
this.inputField = null;
|
||||
|
||||
this.initField(field, databaseClosed);
|
||||
kpxcUI.monitorIconPosition(this);
|
||||
}
|
||||
|
||||
switchIcon(locked) {
|
||||
if (!this.icon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
this.icon.classList.remove(getIconClassName());
|
||||
this.icon.classList.add(getIconClassName(true));
|
||||
this.icon.title = tr('usernameLockedFieldText');
|
||||
} else {
|
||||
this.icon.classList.remove(getIconClassName(true));
|
||||
this.icon.classList.add(getIconClassName());
|
||||
this.icon.title = tr('usernameFieldText');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
UsernameFieldIcon.prototype.initField = function(field, databaseClosed = true) {
|
||||
if (!field || field.getAttribute('kpxc-username-field') === 'true') {
|
||||
return;
|
||||
}
|
||||
|
|
@ -20,36 +47,18 @@ kpxcUsernameField.initField = function(field, databaseClosed = true) {
|
|||
field.setAttribute('kpxc-username-field', 'true');
|
||||
|
||||
// Observer the visibility
|
||||
if (kpxcUsernameField.observer) {
|
||||
kpxcUsernameField.observer.observe(field);
|
||||
if (this.observer) {
|
||||
this.observer.observe(field);
|
||||
}
|
||||
|
||||
createIcon(field, databaseClosed);
|
||||
kpxcUsernameField.inputField = field;
|
||||
this.createIcon(field, databaseClosed);
|
||||
this.inputField = field;
|
||||
};
|
||||
|
||||
kpxcUsernameField.switchIcon = function(locked) {
|
||||
const icons = $('.kpxc-username-icon');
|
||||
if (!icons || icons.length === 0) {
|
||||
return;
|
||||
}
|
||||
const icon = icons;
|
||||
|
||||
if (locked) {
|
||||
icon.classList.remove(getIconClassName());
|
||||
icon.classList.add(getIconClassName(true));
|
||||
icon.title = tr('usernameLockedFieldText');
|
||||
} else {
|
||||
icon.classList.remove(getIconClassName(true));
|
||||
icon.classList.add(getIconClassName());
|
||||
icon.title = tr('usernameFieldText');
|
||||
}
|
||||
};
|
||||
|
||||
const createIcon = function(target, databaseClosed) {
|
||||
UsernameFieldIcon.prototype.createIcon = function(target, databaseClosed) {
|
||||
// Remove any existing password generator icons from the input field
|
||||
if (target.getAttribute('kpxc-password-generator')) {
|
||||
kpxcPassword.removeIcon(target);
|
||||
kpxcPasswordDialog.removeIcon(target);
|
||||
}
|
||||
|
||||
const field = target;
|
||||
|
|
@ -60,7 +69,7 @@ const createIcon = function(target, databaseClosed) {
|
|||
|
||||
// Don't create the icon if the input field is too small
|
||||
if (field.offsetWidth < (size * 1.5) || field.offsetHeight < size) {
|
||||
kpxcUsernameField.observer.unobserve(field);
|
||||
this.observer.unobserve(field);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -79,45 +88,48 @@ const createIcon = function(target, databaseClosed) {
|
|||
icon.style.width = Pixels(size);
|
||||
icon.style.height = Pixels(size);
|
||||
|
||||
icon.addEventListener('click', async function(e) {
|
||||
icon.addEventListener('click', function(e) {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (!kpxcFields.isVisible(field)) {
|
||||
document.body.removeChild(icon);
|
||||
field.removeAttribute('kpxc-username-field');
|
||||
return;
|
||||
}
|
||||
|
||||
const connected = await browser.runtime.sendMessage({ action: 'is_connected' });
|
||||
if (!connected) {
|
||||
kpxcUI.createNotification('error', tr('errorNotConnected'));
|
||||
return;
|
||||
}
|
||||
|
||||
const databaseHash = await browser.runtime.sendMessage({ action: 'check_database_hash' });
|
||||
if (databaseHash === '') {
|
||||
// Triggers database unlock
|
||||
_called.manualFillRequested = ManualFill.BOTH;
|
||||
await browser.runtime.sendMessage({
|
||||
action: 'get_database_hash',
|
||||
args: [ false, true ] // Set triggerUnlock to true
|
||||
});
|
||||
}
|
||||
|
||||
if (icon.className.includes('unlock')) {
|
||||
fillCredentials();
|
||||
}
|
||||
iconClicked(field, icon);
|
||||
});
|
||||
|
||||
kpxcUI.setIconPosition(icon, field);
|
||||
kpxcUsernameField.icon = icon;
|
||||
this.icon = icon;
|
||||
document.body.appendChild(icon);
|
||||
};
|
||||
|
||||
const iconClicked = async function(field, icon) {
|
||||
if (!kpxcFields.isVisible(field)) {
|
||||
document.body.removeChild(icon);
|
||||
field.removeAttribute('kpxc-username-field');
|
||||
return;
|
||||
}
|
||||
|
||||
const connected = await browser.runtime.sendMessage({ action: 'is_connected' });
|
||||
if (!connected) {
|
||||
kpxcUI.createNotification('error', tr('errorNotConnected'));
|
||||
return;
|
||||
}
|
||||
|
||||
const databaseHash = await browser.runtime.sendMessage({ action: 'check_database_hash' });
|
||||
if (databaseHash === '') {
|
||||
// Triggers database unlock
|
||||
_called.manualFillRequested = ManualFill.BOTH;
|
||||
await browser.runtime.sendMessage({
|
||||
action: 'get_database_hash',
|
||||
args: [ false, true ] // Set triggerUnlock to true
|
||||
});
|
||||
}
|
||||
|
||||
if (icon.className.includes('unlock')) {
|
||||
fillCredentials(field);
|
||||
}
|
||||
};
|
||||
|
||||
const getIconClassName = function(locked = false) {
|
||||
if (locked) {
|
||||
return (isFirefox() ? 'lock-moz' : 'lock');
|
||||
|
|
@ -125,22 +137,12 @@ const getIconClassName = function(locked = false) {
|
|||
return (isFirefox() ? 'unlock-moz' : 'unlock');
|
||||
};
|
||||
|
||||
const fillCredentials = function() {
|
||||
const fieldId = kpxcUsernameField.inputField.getAttribute('data-kpxc-id');
|
||||
const fillCredentials = function(field) {
|
||||
const fieldId = field.getAttribute('data-kpxc-id');
|
||||
kpxcFields.prepareId(fieldId);
|
||||
|
||||
const givenType = kpxcUsernameField.inputField.type === 'password' ? 'password' : 'username';
|
||||
const givenType = field.type === 'password' ? 'password' : 'username';
|
||||
const combination = kpxcFields.getCombination(givenType, fieldId);
|
||||
|
||||
kpxc.fillInCredentials(combination, givenType === 'password', false);
|
||||
};
|
||||
|
||||
// Handle icon position on window resize
|
||||
window.addEventListener('resize', function(e) {
|
||||
kpxcUI.updateIconPosition(kpxcUsernameField);
|
||||
});
|
||||
|
||||
// Handle icon position on scroll
|
||||
window.addEventListener('scroll', function(e) {
|
||||
kpxcUI.updateIconPosition(kpxcUsernameField);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -50,15 +50,15 @@
|
|||
],
|
||||
"js": [
|
||||
"browser-polyfill.min.js",
|
||||
"global.js",
|
||||
"content/ui.js",
|
||||
"content/banner.js",
|
||||
"content/autocomplete.js",
|
||||
"content/define.js",
|
||||
"content/keepassxc-browser.js",
|
||||
"content/pwgen.js",
|
||||
"content/sites.js",
|
||||
"content/ui.js",
|
||||
"content/username-field.js",
|
||||
"global.js"
|
||||
"content/username-field.js"
|
||||
],
|
||||
"css": [
|
||||
"css/autocomplete.css",
|
||||
|
|
|
|||
Loading…
Reference in a new issue