mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-19 15:18:02 -04:00
Attach shadowroot to html immediately instead as waiting for element doesn't work (#756)
This commit is contained in:
committed by
Leendert de Borst
parent
60ba96cb86
commit
41d6511eb2
@@ -22,116 +22,88 @@ export default defineContentScript({
|
||||
return;
|
||||
}
|
||||
|
||||
let ui: Awaited<ReturnType<typeof createShadowRootUi>> | null = null;
|
||||
|
||||
/**
|
||||
* Handle input field focus.
|
||||
*/
|
||||
const handleFocusIn = async (e: FocusEvent) : Promise<void> => {
|
||||
if (ctx.isInvalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if element itself, html or body has av-disable attribute like av-disable="true"
|
||||
const avDisable = (e.target as HTMLElement).getAttribute('av-disable') ?? document.body?.getAttribute('av-disable') ?? document.documentElement.getAttribute('av-disable');
|
||||
if (avDisable === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
const target = e.target as HTMLInputElement;
|
||||
const textInputTypes = ['text', 'email', 'tel', 'password', 'search', 'url'];
|
||||
|
||||
if (target.tagName === 'INPUT' && textInputTypes.includes(target.type) && !target.dataset.aliasvaultIgnore) {
|
||||
const formDetector = new FormDetector(document, target);
|
||||
if (!formDetector.containsLoginForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create shadow root UI only if it doesn't exist
|
||||
if (!ui) {
|
||||
ui = await createShadowRootUi(ctx, {
|
||||
name: 'aliasvault-ui',
|
||||
position: 'inline',
|
||||
anchor: target,
|
||||
/**
|
||||
* Inject the icon and potentially show popup.
|
||||
*
|
||||
* @param container - The container element.
|
||||
*/
|
||||
async onMount(container) {
|
||||
injectIcon(target, container);
|
||||
|
||||
// Only show popup if its enabled and debounce time has passed.
|
||||
if (await isAutoShowPopupEnabled() && popupDebounceTimeHasPassed()) {
|
||||
openAutofillPopup(target, container);
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// If UI exists, just inject the icon and potentially show popup
|
||||
injectIcon(target, ui.uiContainer);
|
||||
if (await isAutoShowPopupEnabled() && popupDebounceTimeHasPassed()) {
|
||||
openAutofillPopup(target, ui.uiContainer);
|
||||
// Create a shadow root UI for isolation
|
||||
const ui = await createShadowRootUi(ctx, {
|
||||
name: 'aliasvault-ui',
|
||||
position: 'inline',
|
||||
anchor: 'html',
|
||||
/**
|
||||
* Handle mount.
|
||||
*/
|
||||
onMount(container) {
|
||||
/**
|
||||
* Handle input field focus.
|
||||
*/
|
||||
const handleFocusIn = async (e: FocusEvent) : Promise<void> => {
|
||||
if (ctx.isInvalid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for input field focus in the main document
|
||||
document.addEventListener('focusin', handleFocusIn);
|
||||
// Check if element itself, html or body has av-disable attribute like av-disable="true"
|
||||
const avDisable = (e.target as HTMLElement).getAttribute('av-disable') ?? document.body?.getAttribute('av-disable') ?? document.documentElement.getAttribute('av-disable');
|
||||
if (avDisable === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen for popstate events (back/forward navigation)
|
||||
window.addEventListener('popstate', () => {
|
||||
if (ctx.isInvalid || !ui) {
|
||||
return;
|
||||
}
|
||||
const target = e.target as HTMLInputElement;
|
||||
const textInputTypes = ['text', 'email', 'tel', 'password', 'search', 'url'];
|
||||
|
||||
removeExistingPopup(ui.uiContainer);
|
||||
});
|
||||
if (target.tagName === 'INPUT' && textInputTypes.includes(target.type) && !target.dataset.aliasvaultIgnore) {
|
||||
const formDetector = new FormDetector(document, target);
|
||||
if (!formDetector.containsLoginForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Listen for messages from the background script
|
||||
onMessage('OPEN_AUTOFILL_POPUP', async (message: { data: { elementIdentifier: string } }) : Promise<messageBoolResponse> => {
|
||||
const { data } = message;
|
||||
const { elementIdentifier } = data;
|
||||
|
||||
if (!elementIdentifier) {
|
||||
return { success: false, error: 'No element identifier provided' };
|
||||
}
|
||||
|
||||
const target = document.getElementById(elementIdentifier) ?? document.getElementsByName(elementIdentifier)[0];
|
||||
|
||||
if (!(target instanceof HTMLInputElement)) {
|
||||
return { success: false, error: 'Target element is not an input field' };
|
||||
}
|
||||
|
||||
const formDetector = new FormDetector(document, target);
|
||||
|
||||
if (!formDetector.containsLoginForm()) {
|
||||
return { success: false, error: 'No form found' };
|
||||
}
|
||||
|
||||
// Create shadow root UI if it doesn't exist
|
||||
if (!ui) {
|
||||
ui = await createShadowRootUi(ctx, {
|
||||
name: 'aliasvault-ui',
|
||||
position: 'inline',
|
||||
anchor: target,
|
||||
/**
|
||||
* Inject the icon and show popup.
|
||||
*
|
||||
* @param container - The container element.
|
||||
*/
|
||||
async onMount(container) {
|
||||
injectIcon(target, container);
|
||||
openAutofillPopup(target, container);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
injectIcon(target, ui.uiContainer);
|
||||
openAutofillPopup(target, ui.uiContainer);
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
// Only show popup if its enabled and debounce time has passed.
|
||||
if (await isAutoShowPopupEnabled() && popupDebounceTimeHasPassed()) {
|
||||
openAutofillPopup(target, container);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for input field focus in the main document
|
||||
document.addEventListener('focusin', handleFocusIn);
|
||||
|
||||
// Listen for popstate events (back/forward navigation)
|
||||
window.addEventListener('popstate', () => {
|
||||
if (ctx.isInvalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeExistingPopup(container);
|
||||
});
|
||||
|
||||
// Listen for messages from the background script
|
||||
onMessage('OPEN_AUTOFILL_POPUP', async (message: { data: { elementIdentifier: string } }) : Promise<messageBoolResponse> => {
|
||||
const { data } = message;
|
||||
const { elementIdentifier } = data;
|
||||
|
||||
if (!elementIdentifier) {
|
||||
return { success: false, error: 'No element identifier provided' };
|
||||
}
|
||||
|
||||
const target = document.getElementById(elementIdentifier) ?? document.getElementsByName(elementIdentifier)[0];
|
||||
|
||||
if (!(target instanceof HTMLInputElement)) {
|
||||
return { success: false, error: 'Target element is not an input field' };
|
||||
}
|
||||
|
||||
const formDetector = new FormDetector(document, target);
|
||||
|
||||
if (!formDetector.containsLoginForm()) {
|
||||
return { success: false, error: 'No form found' };
|
||||
}
|
||||
|
||||
injectIcon(target, container);
|
||||
openAutofillPopup(target, container);
|
||||
return { success: true };
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Mount the UI to create the shadow root
|
||||
ui.autoMount();
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user