diff --git a/apps/browser/src/autofill/background/overlay.background.ts b/apps/browser/src/autofill/background/overlay.background.ts index 98d7ea98220..05234f45acb 100644 --- a/apps/browser/src/autofill/background/overlay.background.ts +++ b/apps/browser/src/autofill/background/overlay.background.ts @@ -143,7 +143,7 @@ export class OverlayBackground implements OverlayBackgroundInterface { private platformUtilsService: PlatformUtilsService, private themeStateService: ThemeStateService, ) { - this.initOverlayObservables(); + this.initOverlayEventObservables(); } /** @@ -156,7 +156,10 @@ export class OverlayBackground implements OverlayBackgroundInterface { this.iconsServerUrl = env.getIconsUrl(); } - private initOverlayObservables() { + /** + * Initializes event observables that handle events which affect the overlay's behavior. + */ + private initOverlayEventObservables() { this.repositionInlineMenuSubject .pipe( debounceTime(1000), @@ -594,7 +597,6 @@ export class OverlayBackground implements OverlayBackgroundInterface { } this.clearDelayedInlineMenuClosure(); - this.delayedCloseTimeout = globalThis.setTimeout(() => { const message = { command: "triggerDelayedAutofillInlineMenuClosure" }; this.inlineMenuButtonPort?.postMessage(message); @@ -702,6 +704,11 @@ export class OverlayBackground implements OverlayBackgroundInterface { this.cancelInlineMenuFadeInSubject.next(true); } + /** + * Posts a message to the inline menu elements to trigger a fade in of the inline menu. + * + * @param cancelFadeIn - Signal passed to debounced observable to cancel the fade in + */ private async triggerInlineMenuFadeIn(cancelFadeIn: boolean = false) { if (cancelFadeIn) { return; @@ -1114,33 +1121,6 @@ export class OverlayBackground implements OverlayBackgroundInterface { ); } - /** - * Handles verifying whether the inline menu should be repositioned. This is used to - * guard against removing the inline menu when other frames trigger a resize event. - * - * @param sender - The sender of the message - */ - private checkShouldRepositionInlineMenu(sender: chrome.runtime.MessageSender): boolean { - if (!this.focusedFieldData || sender.tab.id !== this.focusedFieldData.tabId) { - return false; - } - - if (this.focusedFieldData.frameId === sender.frameId) { - return true; - } - - const subFrameOffsetsForTab = this.subFrameOffsetsForTab[sender.tab.id]; - if (subFrameOffsetsForTab) { - for (const value of subFrameOffsetsForTab.values()) { - if (value?.parentFrameIds.includes(sender.frameId)) { - return true; - } - } - } - - return false; - } - /** * Responds to the content script's request to check if the inline menu ciphers are populated. * This will return true only if the sender is the focused field's tab and the inline menu @@ -1176,6 +1156,102 @@ export class OverlayBackground implements OverlayBackgroundInterface { }); } + /** + * Handles verifying whether the inline menu should be repositioned. This is used to + * guard against removing the inline menu when other frames trigger a resize event. + * + * @param sender - The sender of the message + */ + private checkShouldRepositionInlineMenu(sender: chrome.runtime.MessageSender): boolean { + if (!this.focusedFieldData || sender.tab.id !== this.focusedFieldData.tabId) { + return false; + } + + if (this.focusedFieldData.frameId === sender.frameId) { + return true; + } + + const subFrameOffsetsForTab = this.subFrameOffsetsForTab[sender.tab.id]; + if (subFrameOffsetsForTab) { + for (const value of subFrameOffsetsForTab.values()) { + if (value?.parentFrameIds.includes(sender.frameId)) { + return true; + } + } + } + + return false; + } + + /** + * Triggers when a scroll or resize event occurs within a tab. Will reposition the inline menu + * if the focused field is within the viewport. + * + * @param sender - The sender of the message + */ + private async triggerOverlayReposition(sender: chrome.runtime.MessageSender) { + if (this.checkShouldRepositionInlineMenu(sender)) { + this.cancelUpdateInlineMenuPositionSubject.next(); + void this.toggleInlineMenuHidden({ isInlineMenuHidden: true }, sender); + this.repositionInlineMenuSubject.next(sender); + } + } + + /** + * Triggers when a focus event occurs within a tab. Will reposition the inline menu + * if the focused field is within the viewport. + * + * @param sender - The sender of the message + */ + private async triggerSubFrameFocusInRebuild(sender: chrome.runtime.MessageSender) { + this.rebuildSubFrameOffsetsSubject.next(sender); + this.repositionInlineMenuSubject.next(sender); + } + + /** + * Handles determining if the inline menu should be repositioned or closed, and initiates + * the process of calculating the new position of the inline menu. + * + * @param sender - The sender of the message + */ + private repositionInlineMenu = async (sender: chrome.runtime.MessageSender) => { + this.cancelUpdateInlineMenuPositionSubject.next(); + if (!this.isFieldCurrentlyFocused) { + await this.closeInlineMenuAfterReposition(sender); + return; + } + + const isFieldWithinViewport = await BrowserApi.tabSendMessage( + sender.tab, + { command: "checkIsMostRecentlyFocusedFieldWithinViewport" }, + { frameId: this.focusedFieldData.frameId }, + ); + if (!isFieldWithinViewport) { + await this.closeInlineMenuAfterReposition(sender); + return; + } + + if (this.focusedFieldData.frameId > 0) { + this.rebuildSubFrameOffsetsSubject.next(sender); + } + + this.cancelUpdateInlineMenuPositionSubject.next(); + this.startUpdateInlineMenuPositionSubject.next(sender); + }; + + /** + * Triggers a closure of the inline menu during a reposition event. + * + * @param sender - The sender of the message +| */ + private async closeInlineMenuAfterReposition(sender: chrome.runtime.MessageSender) { + await this.toggleInlineMenuHidden( + { isInlineMenuHidden: false, setTransparentInlineMenu: true }, + sender, + ); + this.closeInlineMenu(sender, { forceCloseInlineMenu: true }); + } + /** * Sets up the extension message listeners for the overlay. */ @@ -1342,50 +1418,4 @@ export class OverlayBackground implements OverlayBackgroundInterface { this.inlineMenuButtonPort = null; } }; - - private async triggerOverlayReposition(sender: chrome.runtime.MessageSender) { - if (this.checkShouldRepositionInlineMenu(sender)) { - this.cancelUpdateInlineMenuPositionSubject.next(); - void this.toggleInlineMenuHidden({ isInlineMenuHidden: true }, sender); - this.repositionInlineMenuSubject.next(sender); - } - } - - private async triggerSubFrameFocusInRebuild(sender: chrome.runtime.MessageSender) { - this.rebuildSubFrameOffsetsSubject.next(sender); - this.repositionInlineMenuSubject.next(sender); - } - - private repositionInlineMenu = async (sender: chrome.runtime.MessageSender) => { - this.cancelUpdateInlineMenuPositionSubject.next(); - if (!this.isFieldCurrentlyFocused) { - await this.closeInlineMenuAfterReposition(sender); - return; - } - - const isFieldWithinViewport = await BrowserApi.tabSendMessage( - sender.tab, - { command: "checkIsMostRecentlyFocusedFieldWithinViewport" }, - { frameId: this.focusedFieldData.frameId }, - ); - if (!isFieldWithinViewport) { - await this.closeInlineMenuAfterReposition(sender); - return; - } - - if (this.focusedFieldData.frameId > 0) { - this.rebuildSubFrameOffsetsSubject.next(sender); - } - - this.cancelUpdateInlineMenuPositionSubject.next(); - this.startUpdateInlineMenuPositionSubject.next(sender); - }; - - private async closeInlineMenuAfterReposition(sender: chrome.runtime.MessageSender) { - await this.toggleInlineMenuHidden( - { isInlineMenuHidden: false, setTransparentInlineMenu: true }, - sender, - ); - this.closeInlineMenu(sender, { forceCloseInlineMenu: true }); - } }