feat: MutationObserver for dynamic element suppression
This commit is contained in:
@@ -89,6 +89,15 @@
|
||||
applySettingsToDOM(settings);
|
||||
injectThemeCSS(settings.theme);
|
||||
|
||||
// Start the MutationObserver
|
||||
OR.Observer.start(settings);
|
||||
|
||||
// Apply behavior patches
|
||||
OR.Behavior.start(settings);
|
||||
|
||||
// Start DOM injector (quick actions)
|
||||
OR.Injector.start(settings);
|
||||
|
||||
// Listen for setting changes from popup
|
||||
chrome.storage.onChanged.addListener((changes, area) => {
|
||||
if (area !== 'sync') return;
|
||||
@@ -97,6 +106,15 @@
|
||||
OR.loadSettings().then((updated) => {
|
||||
applySettingsToDOM(updated);
|
||||
|
||||
// Update observer with new settings
|
||||
OR.Observer.updateSettings(updated);
|
||||
|
||||
// Update behavior patches
|
||||
OR.Behavior.updateSettings(updated);
|
||||
|
||||
// Update injector
|
||||
OR.Injector.updateSettings(updated);
|
||||
|
||||
// Swap theme CSS if theme changed
|
||||
if (changes.theme) {
|
||||
injectThemeCSS(changes.theme.newValue);
|
||||
|
||||
@@ -1 +1,126 @@
|
||||
// Outlook Relook — observer.js (stub, implemented in later task)
|
||||
// Outlook Relook — MutationObserver
|
||||
// Watches OWA's DOM and removes dynamically injected elements
|
||||
// based on active settings.
|
||||
|
||||
window.OutlookRelook = window.OutlookRelook || {};
|
||||
|
||||
window.OutlookRelook.Observer = (function () {
|
||||
'use strict';
|
||||
|
||||
let observer = null;
|
||||
let currentSettings = {};
|
||||
|
||||
// Map setting keys to selector registry names
|
||||
// Each setting can suppress one or more logical elements
|
||||
const SETTING_TO_SELECTORS = {
|
||||
hideCopilot: ['copilot-button', 'copilot-pane', 'copilot-compose-suggestions'],
|
||||
hideSuggestedReplies: ['suggested-replies'],
|
||||
hidePromoBanners: ['promo-banners'],
|
||||
hideFocusedOtherTabs: ['focused-other-tabs'],
|
||||
hideSidebarAppIcons: ['sidebar-app-icons'],
|
||||
hideGroupsSection: ['groups-section'],
|
||||
hideMyDayButtons: ['my-day-buttons'],
|
||||
hideSenderAvatars: ['sender-avatars'],
|
||||
hideFeatureDiscovery: ['feature-discovery'],
|
||||
hideVivaInsights: ['viva-insights'],
|
||||
hideUnreadOtherBanner: ['unread-other-banner'],
|
||||
hideActivityFeed: ['activity-feed'],
|
||||
};
|
||||
|
||||
// Text content patterns to match elements by their inner text.
|
||||
// Used when aria/data selectors don't catch dynamically injected content.
|
||||
const TEXT_PATTERNS = {
|
||||
hidePromoBanners: [
|
||||
/try the new outlook/i,
|
||||
/upgrade to premium/i,
|
||||
/get the outlook app/i,
|
||||
/switch to the new/i,
|
||||
],
|
||||
hideFeatureDiscovery: [
|
||||
/what's new/i,
|
||||
/new feature/i,
|
||||
/did you know/i,
|
||||
],
|
||||
};
|
||||
|
||||
function suppressElements() {
|
||||
for (const [settingKey, selectorNames] of Object.entries(SETTING_TO_SELECTORS)) {
|
||||
if (!currentSettings[settingKey]) continue;
|
||||
|
||||
for (const name of selectorNames) {
|
||||
const elements = window.OutlookRelook.resolveSelector(name);
|
||||
for (const el of elements) {
|
||||
if (el.style.display !== 'none') {
|
||||
el.style.display = 'none';
|
||||
console.log('[Outlook Relook] Suppressed: ' + name, el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Text-based suppression for elements missed by selectors
|
||||
for (const [settingKey, patterns] of Object.entries(TEXT_PATTERNS)) {
|
||||
if (!currentSettings[settingKey]) continue;
|
||||
|
||||
for (const pattern of patterns) {
|
||||
// Check buttons, banners, and generic containers
|
||||
const candidates = document.querySelectorAll(
|
||||
'[role="alert"], [role="banner"], [role="dialog"], [role="status"], button, a'
|
||||
);
|
||||
for (const el of candidates) {
|
||||
if (el.style.display === 'none') continue;
|
||||
var text = el.textContent || '';
|
||||
if (pattern.test(text) && text.length < 200) {
|
||||
el.style.display = 'none';
|
||||
console.log('[Outlook Relook] Suppressed by text: "' + text.trim().substring(0, 50) + '"', el);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function start(settings) {
|
||||
currentSettings = settings;
|
||||
|
||||
// Initial pass
|
||||
suppressElements();
|
||||
|
||||
// Watch for DOM mutations
|
||||
observer = new MutationObserver(function (mutations) {
|
||||
// Debounce: only process if nodes were actually added
|
||||
var hasAddedNodes = false;
|
||||
for (var i = 0; i < mutations.length; i++) {
|
||||
if (mutations[i].addedNodes.length > 0) {
|
||||
hasAddedNodes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasAddedNodes) {
|
||||
suppressElements();
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
|
||||
console.log('[Outlook Relook] Observer started');
|
||||
}
|
||||
|
||||
function updateSettings(settings) {
|
||||
currentSettings = settings;
|
||||
// Re-run suppression with new settings
|
||||
suppressElements();
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
console.log('[Outlook Relook] Observer stopped');
|
||||
}
|
||||
}
|
||||
|
||||
return { start: start, updateSettings: updateSettings, stop: stop };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user