[PM-8207] Implementing a way of handling capturing the element at the center point of the inline menu
This commit is contained in:
parent
5a19140619
commit
113db7a1c0
|
@ -38,6 +38,18 @@ export type FocusedFieldData = {
|
|||
frameId?: number;
|
||||
};
|
||||
|
||||
export type InlineMenuElementPosition = {
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
export type InlineMenuPosition = {
|
||||
button?: InlineMenuElementPosition;
|
||||
list?: InlineMenuElementPosition;
|
||||
};
|
||||
|
||||
export type OverlayAddNewItemMessage = {
|
||||
login?: {
|
||||
uri?: string;
|
||||
|
@ -114,6 +126,7 @@ export type OverlayBackgroundExtensionMessageHandlers = {
|
|||
message,
|
||||
sender,
|
||||
}: BackgroundOnMessageHandlerParams) => Promise<void>;
|
||||
getAutofillInlineMenuPosition: () => InlineMenuPosition;
|
||||
toggleAutofillInlineMenuHidden: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
|
||||
checkIsAutofillInlineMenuButtonVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||
checkIsAutofillInlineMenuListVisible: ({ sender }: BackgroundSenderParam) => void;
|
||||
|
|
|
@ -48,6 +48,7 @@ import {
|
|||
SubFrameOffsetData,
|
||||
SubFrameOffsetsForTab,
|
||||
CloseInlineMenuMessage,
|
||||
InlineMenuPosition,
|
||||
} from "./abstractions/overlay.background";
|
||||
|
||||
export class OverlayBackground implements OverlayBackgroundInterface {
|
||||
|
@ -63,6 +64,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
private inlineMenuCiphers: Map<string, CipherView> = new Map();
|
||||
private inlineMenuPageTranslations: Record<string, string>;
|
||||
private inlineMenuFadeInTimeout: number | NodeJS.Timeout;
|
||||
private inlineMenuPosition: InlineMenuPosition = {};
|
||||
private updateInlineMenuPositionTimeout: number | NodeJS.Timeout;
|
||||
private delayedCloseTimeout: number | NodeJS.Timeout;
|
||||
private focusedFieldData: FocusedFieldData;
|
||||
|
@ -87,6 +89,7 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
focusAutofillInlineMenuList: () => this.focusInlineMenuList(),
|
||||
updateAutofillInlineMenuPosition: ({ message, sender }) =>
|
||||
this.updateInlineMenuPosition(message, sender),
|
||||
getAutofillInlineMenuPosition: () => this.getInlineMenuPosition(),
|
||||
toggleAutofillInlineMenuHidden: ({ message, sender }) =>
|
||||
this.updateInlineMenuHidden(message, sender),
|
||||
checkIsAutofillInlineMenuButtonVisible: ({ sender }) =>
|
||||
|
@ -641,6 +644,13 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the currently open inline menu.
|
||||
*/
|
||||
private getInlineMenuPosition(): InlineMenuPosition {
|
||||
return this.inlineMenuPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles updating the opacity of both the inline menu button and list.
|
||||
* This is used to simultaneously fade in the inline menu elements.
|
||||
|
@ -682,11 +692,18 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
? subFrameLeftOffset + left + width - height - (fieldPaddingRight - elementOffset + 2)
|
||||
: subFrameLeftOffset + left + width - height + elementOffset / 2;
|
||||
|
||||
this.inlineMenuPosition.button = {
|
||||
top: Math.round(elementTopPosition),
|
||||
left: Math.round(elementLeftPosition),
|
||||
height: Math.round(elementHeight),
|
||||
width: Math.round(elementHeight),
|
||||
};
|
||||
|
||||
return {
|
||||
top: `${Math.round(elementTopPosition)}px`,
|
||||
left: `${Math.round(elementLeftPosition)}px`,
|
||||
height: `${Math.round(elementHeight)}px`,
|
||||
width: `${Math.round(elementHeight)}px`,
|
||||
top: `${this.inlineMenuPosition.button.top}px`,
|
||||
left: `${this.inlineMenuPosition.button.left}px`,
|
||||
height: `${this.inlineMenuPosition.button.height}px`,
|
||||
width: `${this.inlineMenuPosition.button.width}px`,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -699,10 +716,18 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
const subFrameLeftOffset = subFrameOffsets?.left || 0;
|
||||
|
||||
const { top, left, width, height } = this.focusedFieldData.focusedFieldRects;
|
||||
|
||||
this.inlineMenuPosition.list = {
|
||||
top: Math.round(top + height + subFrameTopOffset),
|
||||
left: Math.round(left + subFrameLeftOffset),
|
||||
height: 0,
|
||||
width: Math.round(width),
|
||||
};
|
||||
|
||||
return {
|
||||
width: `${Math.round(width)}px`,
|
||||
top: `${Math.round(top + height + subFrameTopOffset)}px`,
|
||||
left: `${Math.round(left + subFrameLeftOffset)}px`,
|
||||
width: `${this.inlineMenuPosition.list.width}px`,
|
||||
top: `${this.inlineMenuPosition.list.top}px`,
|
||||
left: `${this.inlineMenuPosition.list.left}px`,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1110,6 +1135,11 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
* @param message - Contains the dimensions of the inline menu list
|
||||
*/
|
||||
private updateInlineMenuListHeight(message: OverlayBackgroundExtensionMessage) {
|
||||
const parsedHeight = parseInt(message.styles?.height);
|
||||
if (this.inlineMenuPosition.list && parsedHeight > 0) {
|
||||
this.inlineMenuPosition.list.height = parsedHeight;
|
||||
}
|
||||
|
||||
this.inlineMenuListPort?.postMessage({
|
||||
command: "updateAutofillInlineMenuPosition",
|
||||
styles: message.styles,
|
||||
|
@ -1276,10 +1306,12 @@ export class OverlayBackground implements OverlayBackgroundInterface {
|
|||
private handlePortOnDisconnect = (port: chrome.runtime.Port) => {
|
||||
if (port.name === AutofillOverlayPort.List) {
|
||||
this.inlineMenuListPort = null;
|
||||
this.inlineMenuPosition.list = null;
|
||||
}
|
||||
|
||||
if (port.name === AutofillOverlayPort.Button) {
|
||||
this.inlineMenuButtonPort = null;
|
||||
this.inlineMenuPosition.button = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import {
|
||||
InlineMenuElementPosition,
|
||||
InlineMenuPosition,
|
||||
} from "../../../background/abstractions/overlay.background";
|
||||
import { AutofillExtensionMessage } from "../../../content/abstractions/autofill-init";
|
||||
import { AutofillOverlayElement } from "../../../enums/autofill-overlay.enum";
|
||||
import {
|
||||
|
@ -27,6 +31,7 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
|||
private bodyElementMutationObserver: MutationObserver;
|
||||
private mutationObserverIterations = 0;
|
||||
private mutationObserverIterationsResetTimeout: number | NodeJS.Timeout;
|
||||
private lastElementOverrides: WeakMap<Element, number> = new WeakMap();
|
||||
private readonly customElementDefaultStyles: Partial<CSSStyleDeclaration> = {
|
||||
all: "initial",
|
||||
position: "fixed",
|
||||
|
@ -386,11 +391,14 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
|||
return;
|
||||
}
|
||||
|
||||
if (!lastChildIsInlineMenuList && !lastChildIsInlineMenuButton) {
|
||||
const lastChildZIndex = parseInt((lastChild as HTMLElement).style.zIndex);
|
||||
if (lastChildZIndex >= 2147483647) {
|
||||
(lastChild as HTMLElement).style.zIndex = "2147483646";
|
||||
}
|
||||
const lastChildEncounterCount = this.lastElementOverrides.get(lastChild) || 0;
|
||||
if (!lastChildIsInlineMenuList && !lastChildIsInlineMenuButton && lastChildEncounterCount < 3) {
|
||||
this.lastElementOverrides.set(lastChild, lastChildEncounterCount + 1);
|
||||
}
|
||||
|
||||
if (this.lastElementOverrides.get(lastChild) >= 3) {
|
||||
await this.handlePersistentLastChildOverride(lastChild);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -412,6 +420,46 @@ export class AutofillInlineMenuContentService implements AutofillInlineMenuConte
|
|||
globalThis.document.body.insertBefore(lastChild, this.buttonElement);
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies if the last child of the body element is overlaying the inline menu elements.
|
||||
* This is triggered when the last child of the body is being forced by some script to
|
||||
* be an element other than the inline menu elements.
|
||||
*
|
||||
* @param lastChild - The last child of the body element.
|
||||
*/
|
||||
private async handlePersistentLastChildOverride(lastChild: Element) {
|
||||
const lastChildZIndex = parseInt((lastChild as HTMLElement).style.zIndex);
|
||||
if (lastChildZIndex >= 2147483647) {
|
||||
(lastChild as HTMLElement).style.zIndex = "2147483646";
|
||||
}
|
||||
|
||||
const inlineMenuPosition: InlineMenuPosition = await this.sendExtensionMessage(
|
||||
"getAutofillInlineMenuPosition",
|
||||
);
|
||||
const { button, list } = inlineMenuPosition;
|
||||
|
||||
if (!!button && this.elementAtCenterOfInlineMenuPosition(button) === lastChild) {
|
||||
this.closeInlineMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!list && this.elementAtCenterOfInlineMenuPosition(list) === lastChild) {
|
||||
this.closeInlineMenu();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element present at the center of the inline menu position.
|
||||
*
|
||||
* @param position - The position of the inline menu element.
|
||||
*/
|
||||
private elementAtCenterOfInlineMenuPosition(position: InlineMenuElementPosition): Element | null {
|
||||
return globalThis.document.elementFromPoint(
|
||||
position.left + position.width / 2,
|
||||
position.top + position.height / 2,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies if the mutation observer is triggering excessive iterations.
|
||||
* Will trigger a blur of the most recently focused field and remove the
|
||||
|
|
Loading…
Reference in New Issue