From c5f6772893ef61971e47c2134eead464a7ac8576 Mon Sep 17 00:00:00 2001 From: Jeffrey Holland Date: Mon, 8 Sep 2025 11:49:58 +0200 Subject: [PATCH] Alternative change for PM-24720 without changing index check --- .../autofill-overlay-content.service.ts | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts index 51b7c8c603c..af9c14efffb 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -75,6 +75,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ private focusedFieldData: FocusedFieldData; private closeInlineMenuOnRedirectTimeout: number | NodeJS.Timeout; private focusInlineMenuListTimeout: number | NodeJS.Timeout; + private blurFieldTimeout: number | NodeJS.Timeout; private eventHandlersMemo: { [key: string]: EventListener } = {}; private readonly extensionMessageHandlers: AutofillOverlayContentExtensionMessageHandlers = { addNewVaultItemFromOverlay: ({ message }) => this.addNewVaultItem(message), @@ -687,11 +688,27 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ /** * Form Field blur event handler. Updates the value identifying whether * the field is focused and sends a message to check if the inline menu itself - * is currently focused. + * is currently focused. Uses a timeout to allow checking if another form field + * is being focused to avoid premature overlay closure during field transitions. */ private handleFormFieldBlurEvent = () => { - void this.updateIsFieldCurrentlyFocused(false); - void this.sendExtensionMessage("checkAutofillInlineMenuFocused"); + if (this.blurFieldTimeout) { + clearTimeout(this.blurFieldTimeout); + } + + this.blurFieldTimeout = globalThis.setTimeout(() => { + const activeElement = this.getRootNodeActiveElement(this.mostRecentlyFocusedField); + const isFormFieldFocused = + activeElement && + this.formFieldElements.has(activeElement as ElementWithOpId); + + if (!isFormFieldFocused) { + void this.updateIsFieldCurrentlyFocused(false); + void this.sendExtensionMessage("checkAutofillInlineMenuFocused"); + } + + this.blurFieldTimeout = null; + }, 100); }; /** @@ -913,6 +930,8 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ * @param formFieldElement - The form field element that triggered the focus event. */ private async triggerFormFieldFocusedAction(formFieldElement: ElementWithOpId) { + this.clearBlurFieldTimeout(); + if (await this.isFieldCurrentlyFilling()) { return; } @@ -1787,6 +1806,16 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ } } + /** + * Clears the timeout that handles blur event transitions between fields. + */ + private clearBlurFieldTimeout() { + if (this.blurFieldTimeout) { + globalThis.clearTimeout(this.blurFieldTimeout); + this.blurFieldTimeout = null; + } + } + /** * Destroys the autofill overlay content service. This method will * disconnect the mutation observers and remove all event listeners. @@ -1794,6 +1823,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ destroy() { this.clearFocusInlineMenuListTimeout(); this.clearCloseInlineMenuOnRedirectTimeout(); + this.clearBlurFieldTimeout(); this.formFieldElements.forEach((_autofillField, formFieldElement) => { this.removeCachedFormFieldEventListeners(formFieldElement); formFieldElement.removeEventListener(EVENTS.BLUR, this.handleFormFieldBlurEvent);