04/26 Enhanced extension functions

This commit is contained in:
2026-04-26 09:44:54 -04:00
parent 747a9124c2
commit 194601e461
5 changed files with 1470 additions and 13 deletions
+38 -4
View File
@@ -45,6 +45,21 @@
return true;
}
/**
* Returns a debounced version of `fn` that waits `ms` milliseconds after
* the last call before firing. Used to avoid re-rendering the dropdown on
* every keystroke.
*/
function _debounce(fn, ms) {
var timer;
return function () {
var args = arguments;
var ctx = this;
clearTimeout(timer);
timer = setTimeout(function () { fn.apply(ctx, args); }, ms);
};
}
function visiblePasswordFields() {
return Array.from(document.querySelectorAll('input[type="password"]'))
.filter(el => isVisible(el) && !el.disabled);
@@ -621,10 +636,12 @@
showDropdown(field, pwField, field.value, 'credentials');
}, { signal: abortSignal });
// Re-filter as user types.
field.addEventListener('input', function () {
// Re-filter as user types — debounced to avoid rebuilding the dropdown
// on every single keystroke (noticeable on large vaults or slow machines).
var _debouncedShow = _debounce(function () {
showDropdown(field, pwField, field.value, 'credentials');
}, { signal: abortSignal });
}, 150);
field.addEventListener('input', _debouncedShow, { signal: abortSignal });
// Dim button when field loses focus and no dropdown is open.
field.addEventListener('blur', function () {
@@ -901,7 +918,24 @@
}
});
_formObserver = new MutationObserver(function () {
_formObserver = new MutationObserver(function (mutations) {
// Ignore mutations caused by the extension's own injected elements
// (dropdown, icon buttons, save banner) to prevent re-decoration loops
// on SPAs that react to every DOM change.
var ownMutation = mutations.every(function (m) {
return Array.from(m.addedNodes).concat(Array.from(m.removedNodes)).every(function (node) {
if (!node || node.nodeType !== 1) return true;
var cls = (node.className || '');
var id = (node.id || '');
return cls.indexOf('__pk') !== -1 ||
id.indexOf('__pk') !== -1 ||
node.querySelector && (
node.querySelector('.' + PK_BTN_CLASS) ||
node.querySelector('#' + PK_DROPDOWN_ID)
);
});
});
if (ownMutation) return;
_hasNotifiedForm = false;
notifyFormDetected();
decorateFields();