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 cdfdde3e4f..2b7ceb092e 100644 --- a/apps/browser/src/autofill/services/autofill-overlay-content.service.ts +++ b/apps/browser/src/autofill/services/autofill-overlay-content.service.ts @@ -31,6 +31,7 @@ import AutofillField from "../models/autofill-field"; import AutofillPageDetails from "../models/autofill-page-details"; import { ElementWithOpId, FillableFormFieldElement, FormFieldElement } from "../types"; import { + debounce, elementIsFillableFormField, elementIsSelectElement, getAttributeBoolean, @@ -670,9 +671,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ * is currently focused. */ private handleFormFieldBlurEvent = () => { - void this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { - isFieldCurrentlyFocused: false, - }); + void this.updateIsFieldCurrentlyFocused(false); void this.sendExtensionMessage("checkAutofillInlineMenuFocused"); }; @@ -733,7 +732,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ */ private handleFormFieldInputEvent = (formFieldElement: ElementWithOpId) => { return this.useEventHandlersMemo( - () => this.triggerFormFieldInput(formFieldElement), + debounce(() => this.triggerFormFieldInput(formFieldElement), 100, true), this.getFormFieldHandlerMemoIndex(formFieldElement, EVENTS.INPUT), ); }; @@ -755,7 +754,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ return; } - if (await this.hideInlineMenuListOnFilledField(formFieldElement)) { + if (formFieldElement?.value) { void this.sendExtensionMessage("closeAutofillInlineMenu", { overlayElement: AutofillOverlayElement.List, forceCloseInlineMenu: true, @@ -911,9 +910,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ return; } - await this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { - isFieldCurrentlyFocused: true, - }); + await this.updateIsFieldCurrentlyFocused(true); const initiallyFocusedField = this.mostRecentlyFocusedField; await this.updateMostRecentlyFocusedField(formFieldElement); @@ -935,9 +932,13 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ return; } - void this.sendExtensionMessage("openAutofillInlineMenu"); + await this.sendExtensionMessage("openAutofillInlineMenu"); } + private updateIsFieldCurrentlyFocused = async (isFieldCurrentlyFocused: boolean) => { + await this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { isFieldCurrentlyFocused }); + }; + /** * Validates whether the user is currently authenticated. */ diff --git a/apps/browser/src/autofill/utils/index.ts b/apps/browser/src/autofill/utils/index.ts index 98c0a97ac5..8d44408f2e 100644 --- a/apps/browser/src/autofill/utils/index.ts +++ b/apps/browser/src/autofill/utils/index.ts @@ -378,12 +378,26 @@ export function throttle(callback: (_args: any) => any, limit: number) { * * @param callback - The callback function to debounce. * @param delay - The time in milliseconds to debounce the callback. + * @param immediate - Determines whether the callback should run immediately. */ -export function debounce(callback: (_args: any) => any, delay: number) { +export function debounce(callback: (_args: any) => any, delay: number, immediate?: boolean) { let timeout: NodeJS.Timeout; return function (...args: unknown[]) { - globalThis.clearTimeout(timeout); - timeout = globalThis.setTimeout(() => callback.apply(this, args), delay); + const callImmediately = !!immediate && !timeout; + + if (timeout) { + globalThis.clearTimeout(timeout); + } + timeout = globalThis.setTimeout(() => { + timeout = null; + if (!callImmediately) { + callback.apply(this, args); + } + }, delay); + + if (callImmediately) { + callback.apply(this, args); + } }; }