Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for checkboxes with Custom Login Fields #2372

Merged
merged 1 commit into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions keepassxc-browser/content/custom-fields-banner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const STEP_SELECT_PASSWORD = 2;
const STEP_SELECT_TOTP = 3;
const STEP_SELECT_STRING_FIELDS = 4;

const CHECKBOX_OVERLAY_SIZE = 20;

const DEFINED_CUSTOM_FIELDS = 'defined-custom-fields';
const FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field';
const DARK_FIXED_FIELD_CLASS = 'kpxcDefine-fixed-field-dark';
Expand All @@ -17,14 +19,19 @@ const PASSWORD_FIELD_CLASS = 'kpxcDefine-fixed-password-field';
const TOTP_FIELD_CLASS = 'kpxcDefine-fixed-totp-field';
const STRING_FIELD_CLASS = 'kpxcDefine-fixed-string-field';

const inputQueryPatternStart = 'input';
const inputQueryPatternNotCheckbox = ':not([type=checkbox])';
const inputQueryPattern = ':not([disabled]):not([type=button]):not([type=radio]):not([type=color]):not([type=date]):not([type=datetime-local]):not([type=file]):not([type=hidden]):not([type=image]):not([type=month]):not([type=range]):not([type=reset]):not([type=submit]):not([type=time]):not([type=week]), select, textarea';

const kpxcCustomLoginFieldsBanner = {};
kpxcCustomLoginFieldsBanner.banner = undefined;
kpxcCustomLoginFieldsBanner.chooser = undefined;
kpxcCustomLoginFieldsBanner.created = false;
kpxcCustomLoginFieldsBanner.dataStep = STEP_NONE;
kpxcCustomLoginFieldsBanner.infoText = undefined;
kpxcCustomLoginFieldsBanner.wrapper = undefined;
kpxcCustomLoginFieldsBanner.inputQueryPattern = 'input:not([type=button]):not([type=checkbox]):not([type=color]):not([type=date]):not([type=datetime-local]):not([type=file]):not([type=hidden]):not([type=image]):not([type=month]):not([type=range]):not([type=reset]):not([type=submit]):not([type=time]):not([type=week]), select, textarea';
kpxcCustomLoginFieldsBanner.inputQueryPatternNormal = inputQueryPatternStart + inputQueryPatternNotCheckbox + inputQueryPattern;
kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields = inputQueryPatternStart + inputQueryPattern;
kpxcCustomLoginFieldsBanner.markedFields = [];
kpxcCustomLoginFieldsBanner.nonSelectedElementsPattern = `div.${FIXED_FIELD_CLASS}:not(.${USERNAME_FIELD_CLASS}):not(.${PASSWORD_FIELD_CLASS}):not(.${TOTP_FIELD_CLASS}):not(.${STRING_FIELD_CLASS})`;

Expand Down Expand Up @@ -55,7 +62,8 @@ kpxcCustomLoginFieldsBanner.destroy = async function() {
kpxcCustomLoginFieldsBanner.created = false;
kpxcCustomLoginFieldsBanner.close();

if (kpxcCustomLoginFieldsBanner.wrapper && window.self.document.body.contains(kpxcCustomLoginFieldsBanner.wrapper)) {
if (kpxcCustomLoginFieldsBanner.wrapper
&& window.self.document.body.contains(kpxcCustomLoginFieldsBanner.wrapper)) {
window.self.document.body.removeChild(kpxcCustomLoginFieldsBanner.wrapper);
} else {
window.self.document.body.removeChild(window.parent.document.body.querySelector('#kpxc-banner'));
Expand Down Expand Up @@ -507,7 +515,10 @@ kpxcCustomLoginFieldsBanner.selectStringFields = function() {

kpxcCustomLoginFieldsBanner.markFields = function() {
let firstInput;
const inputs = document.querySelectorAll(kpxcCustomLoginFieldsBanner.inputQueryPattern);
const inputs = document.querySelectorAll(
kpxcCustomLoginFieldsBanner.dataStep === STEP_SELECT_STRING_FIELDS
? kpxcCustomLoginFieldsBanner.inputQueryPatternStringFields
: kpxcCustomLoginFieldsBanner.inputQueryPatternNormal);
const zoom = kpxcUI.bodyStyle.zoom || 1;

for (const i of inputs) {
Expand All @@ -528,7 +539,17 @@ kpxcCustomLoginFieldsBanner.markFields = function() {
field.style.left = Pixels(rect.left / zoom);
field.style.width = Pixels(rect.width / zoom);
field.style.height = Pixels(rect.height / zoom);
field.textContent = dataStepToString();

// Don't show the default overlay text on checkboxes. Applied only after selection.
if (kpxcCustomLoginFieldsBanner.dataStep !== STEP_SELECT_STRING_FIELDS) {
field.textContent = dataStepToString();
}

// Static size for the checkbox overlay
if (i?.getLowerCaseAttribute('type') === 'checkbox') {
field.style.width = Pixels(CHECKBOX_OVERLAY_SIZE / zoom);
field.style.height = Pixels(CHECKBOX_OVERLAY_SIZE / zoom);
}

// Change selection theme if needed
const isLightTheme = isLightThemeBackground(i);
Expand Down Expand Up @@ -619,6 +640,11 @@ kpxcCustomLoginFieldsBanner.setSelectionPosition = function(field) {

field.style.top = Pixels(top + scrollTop);
field.style.left = Pixels(left + scrollLeft);

if (field.originalElement?.getLowerCaseAttribute('type') === 'checkbox') {
// Position the overlay to the center of checkbox
field.style.transform = 'translate(-25%, -25%)';
}
};

kpxcCustomLoginFieldsBanner.getNonSelectedElements = function() {
Expand Down
4 changes: 3 additions & 1 deletion keepassxc-browser/content/keepassxc-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ kpxc.setPasswordFilled = async function(state) {
await sendMessage('password_set_filled', state);
};

// Special handling for settings value to select element
// Special handling for setting value to select and checkbox elements
kpxc.setValue = function(field, value, forced = false) {
if (field.matches('select')) {
value = value.toLowerCase().trim();
Expand All @@ -712,6 +712,8 @@ kpxc.setValue = function(field, value, forced = false) {
}

return;
} else if (field.getLowerCaseAttribute('type') === 'checkbox' && value?.toLowerCase() === 'true') {
field.checked = true;
}

kpxc.setValueWithChange(field, value, forced);
Expand Down