From ab485379a6b243a1059b992163b06f6d2919f6f1 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 7 Mar 2021 11:54:57 +0200 Subject: [PATCH] Add icon to the right side of the segmented fields --- keepassxc-browser/content/keepassxc-browser.js | 10 +++++++++- keepassxc-browser/content/totp-field.js | 18 +++++++++--------- keepassxc-browser/content/ui.js | 16 +++++++++++----- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js index 69c12dc..a6808c2 100755 --- a/keepassxc-browser/content/keepassxc-browser.js +++ b/keepassxc-browser/content/keepassxc-browser.js @@ -397,6 +397,14 @@ kpxcFields.getSegmentedTOTPFields = function(inputs, combinations) { }; combinations.push(combination); + + // Create an icon to the right side of the segmented fields + kpxcTOTPIcons.newIcon(totpInputs[totpInputs.length - 1], kpxc.databaseState, true); + kpxcIcons.icons.push({ + field: totpInputs[totpInputs.length - 1], + iconType: kpxcIcons.iconTypes.TOTP, + segmented: true + }); } } @@ -617,7 +625,7 @@ kpxcFields.useCustomLoginFields = async function() { // Handle custom TOTP field if (totp) { totp.setAttribute('kpxc-defined', 'totp'); - kpxcTOTPIcons.newIcon(totp, kpxc.databaseState, true); + kpxcTOTPIcons.newIcon(totp, kpxc.databaseState); } const combinations = []; diff --git a/keepassxc-browser/content/totp-field.js b/keepassxc-browser/content/totp-field.js index 0059d0c..e4af242 100644 --- a/keepassxc-browser/content/totp-field.js +++ b/keepassxc-browser/content/totp-field.js @@ -20,8 +20,8 @@ const acceptedOTPFields = [ var kpxcTOTPIcons = {}; kpxcTOTPIcons.icons = []; -kpxcTOTPIcons.newIcon = function(field, databaseState = DatabaseState.DISCONNECTED, forced = false) { - kpxcTOTPIcons.icons.push(new TOTPFieldIcon(field, databaseState, forced)); +kpxcTOTPIcons.newIcon = function(field, databaseState = DatabaseState.DISCONNECTED, segmented = false) { + kpxcTOTPIcons.icons.push(new TOTPFieldIcon(field, databaseState, segmented)); }; kpxcTOTPIcons.switchIcon = function(state) { @@ -76,25 +76,25 @@ kpxcTOTPIcons.isValid = function(field, forced) { }; class TOTPFieldIcon extends Icon { - constructor(field, databaseState = DatabaseState.DISCONNECTED, forced = false) { - super(field, databaseState); + constructor(field, databaseState = DatabaseState.DISCONNECTED, segmented = false) { + super(field, databaseState, segmented); - this.initField(field, forced); + this.initField(field, segmented); kpxcUI.monitorIconPosition(this); } } -TOTPFieldIcon.prototype.initField = function(field, forced) { +TOTPFieldIcon.prototype.initField = function(field, segmented) { // Observer the visibility if (this.observer) { this.observer.observe(field); } - this.createIcon(field); + this.createIcon(field, segmented); this.inputField = field; }; -TOTPFieldIcon.prototype.createIcon = function(field) { +TOTPFieldIcon.prototype.createIcon = function(field, segmented = false) { const className = (isFirefox() ? 'moz' : 'default'); // Size the icon dynamically, but not greater than 24 or smaller than 14 @@ -126,7 +126,7 @@ TOTPFieldIcon.prototype.createIcon = function(field) { kpxc.fillFromTOTP(field); }); - kpxcUI.setIconPosition(icon, field, this.rtl); + kpxcUI.setIconPosition(icon, field, this.rtl, segmented); this.icon = icon; const styleSheet = document.createElement('link'); diff --git a/keepassxc-browser/content/ui.js b/keepassxc-browser/content/ui.js index b6a6226..b8018d2 100644 --- a/keepassxc-browser/content/ui.js +++ b/keepassxc-browser/content/ui.js @@ -23,11 +23,12 @@ const Pixels = function(value) { // Basic icon class class Icon { - constructor(field, databaseState = DatabaseState.DISCONNECTED) { + constructor(field, databaseState = DatabaseState.DISCONNECTED, segmented = false) { this.databaseState = databaseState; this.icon = null; this.inputField = null; this.rtl = kpxcUI.isRTL(field); + this.segmented = segmented; try { this.observer = new IntersectionObserver((entries) => { @@ -103,7 +104,7 @@ kpxcUI.monitorIconPosition = function(iconClass) { kpxcUI.updateIconPosition = function(iconClass) { if (iconClass.inputField && iconClass.icon) { - kpxcUI.setIconPosition(iconClass.icon, iconClass.inputField, iconClass.rtl); + kpxcUI.setIconPosition(iconClass.icon, iconClass.inputField, iconClass.rtl, iconClass.segmented); } }; @@ -112,13 +113,18 @@ kpxcUI.calculateIconOffset = function(field, size) { return (offset < 0) ? 0 : offset; }; -kpxcUI.setIconPosition = function(icon, field, rtl = false) { +kpxcUI.setIconPosition = function(icon, field, rtl = false, segmented = false) { const rect = field.getBoundingClientRect(); const size = Number(icon.getAttribute('size')); const offset = kpxcUI.calculateIconOffset(field, size); - const left = kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.left - kpxcUI.bodyRect.left : rect.left; + let left = kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.left - kpxcUI.bodyRect.left : rect.left; const top = kpxcUI.bodyStyle.position.toLowerCase() === 'relative' ? rect.top - kpxcUI.bodyRect.top : rect.top; + // Add more space for the icon to show it at the right side of the field if TOTP fields are segmented + if (segmented) { + left += size + 10; + } + icon.style.top = Pixels(top + document.scrollingElement.scrollTop + offset + 1); icon.style.left = rtl ? Pixels((left + document.scrollingElement.scrollLeft) + offset) @@ -181,7 +187,7 @@ kpxcUI.updateFromIntersectionObserver = function(iconClass, entries) { // Wait for possible DOM animations setTimeout(() => { - kpxcUI.setIconPosition(iconClass.icon, entry.target, iconClass.rtl); + kpxcUI.setIconPosition(iconClass.icon, entry.target, iconClass.rtl, iconClass.segmented); }, 400); } }