Files
Outcut/content/content.js
Joel Brock 3de2db7d89 rename: Outlook Relook → Outcut, add keyboard presets, remove design UI from popup
- Rename extension to "Outcut" throughout all source files and console logs
- Add KEY_PRESETS object (gmail/outlook) and matchesAction() helper to keyboard.js
- Rewrite handleKeydown to use preset-based dispatch instead of hardcoded switch
- Update updateSettings to re-init when keyboardPreset changes
- Add keyboardPreset: 'gmail' default to settings-defaults.js
- Replace popup Design Tweaks UI with preset dropdown + dynamic help text
- Keep all design tweak content script logic intact (activatable via storage)
- Update manifest: version 1.0.0, remove activeTab, add homepage_url
2026-04-27 14:11:45 -07:00

166 lines
5.7 KiB
JavaScript

// Outlook Relook — Content Script Entry Point
//
// Primary feature: Keyboard navigation (always active)
// Experimental: Design tweaks (themes, density, hiding, behavior) — gated by enableDesignTweaks
(function () {
'use strict';
const OR = window.OutlookRelook;
// Map setting keys to data attributes on <html> (design tweaks only)
const SETTING_TO_ATTR = {
compactTopBar: 'data-or-compact-topbar',
compactCommandBar: 'data-or-compact-commandbar',
compactMessageList: 'data-or-compact-messagelist',
compactReadingPane: 'data-or-compact-readingpane',
compactFolderPane: 'data-or-compact-folderpane',
narrowDateColumn: 'data-or-narrow-datecol',
compressComposeToolbar:'data-or-compact-compose',
readingPaneMaxWidth: 'data-or-reading-maxwidth',
unifiedHeader: 'data-or-unified-header',
hideCopilot: 'data-or-hide-copilot',
hideSuggestedReplies: 'data-or-hide-suggestedreplies',
hidePromoBanners: 'data-or-hide-promos',
hideFocusedOtherTabs: 'data-or-hide-focusedtabs',
hideSidebarAppIcons: 'data-or-hide-sidebaricons',
hideGroupsSection: 'data-or-hide-groups',
hideMyDayButtons: 'data-or-hide-myday',
hideSenderAvatars: 'data-or-hide-avatars',
hideFeatureDiscovery: 'data-or-hide-discovery',
hideVivaInsights: 'data-or-hide-viva',
hideUnreadOtherBanner: 'data-or-hide-unreadother',
hideActivityFeed: 'data-or-hide-activity',
unreadDistinction: 'data-or-unread-distinction',
previewOwnLine: 'data-or-preview-own-line',
normalizeFontWeight: 'data-or-normalize-font',
darkModeEmailFix: 'data-or-darkmode-fix',
};
const SETTING_TO_ATTR_VALUE = {
messageListFontSize: 'data-or-fontsize',
};
let designTweaksActive = false;
function applyColorScheme(scheme) {
let resolved = scheme;
if (scheme === 'system') {
resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
document.documentElement.setAttribute('data-outlook-relook-scheme', resolved);
}
function applySettingsToDOM(settings) {
for (const [key, attr] of Object.entries(SETTING_TO_ATTR)) {
document.documentElement.setAttribute(attr, String(!!settings[key]));
}
for (const [key, attr] of Object.entries(SETTING_TO_ATTR_VALUE)) {
document.documentElement.setAttribute(attr, settings[key] || '');
}
applyColorScheme(settings.colorScheme);
if (settings.accentColor) {
document.documentElement.style.setProperty('--or-accent-override', settings.accentColor);
}
console.log('[Outcut] Settings applied to DOM');
}
function clearDesignFromDOM() {
// Remove all data-or-* attributes
for (const attr of Object.values(SETTING_TO_ATTR)) {
document.documentElement.removeAttribute(attr);
}
for (const attr of Object.values(SETTING_TO_ATTR_VALUE)) {
document.documentElement.removeAttribute(attr);
}
document.documentElement.removeAttribute('data-outlook-relook-scheme');
document.documentElement.style.removeProperty('--or-accent-override');
// Remove injected theme CSS
var themeLink = document.getElementById('outlook-relook-theme');
if (themeLink) themeLink.remove();
console.log('[Outcut] Design tweaks cleared from DOM');
}
function injectThemeCSS(theme) {
var existing = document.getElementById('outlook-relook-theme');
if (existing) existing.remove();
var link = document.createElement('link');
link.id = 'outlook-relook-theme';
link.rel = 'stylesheet';
link.href = chrome.runtime.getURL('themes/' + theme + '.css');
document.head.appendChild(link);
console.log('[Outcut] Theme loaded: ' + theme);
}
function startDesignTweaks(settings) {
applySettingsToDOM(settings);
injectThemeCSS(settings.theme);
OR.Observer.start(settings);
OR.Behavior.start(settings);
OR.Injector.start(settings);
designTweaksActive = true;
console.log('[Outcut] Design tweaks enabled');
}
function stopDesignTweaks() {
OR.Observer.stop();
OR.Behavior.stop();
OR.Injector.stop();
clearDesignFromDOM();
designTweaksActive = false;
console.log('[Outcut] Design tweaks disabled');
}
async function init() {
const settings = await OR.loadSettings();
console.log('[Outcut] Loaded settings:', settings);
// Keyboard navigation — always starts (gated by its own toggle internally)
OR.Keyboard.start(settings);
// Design tweaks — only if enabled
if (settings.enableDesignTweaks) {
startDesignTweaks(settings);
}
// Listen for setting changes from popup
chrome.storage.onChanged.addListener((changes, area) => {
if (area !== 'sync') return;
OR.loadSettings().then((updated) => {
// Keyboard — always update
OR.Keyboard.updateSettings(updated);
// Design tweaks — toggle on/off or update
if (updated.enableDesignTweaks) {
if (!designTweaksActive) {
startDesignTweaks(updated);
} else {
applySettingsToDOM(updated);
OR.Observer.updateSettings(updated);
OR.Behavior.updateSettings(updated);
OR.Injector.updateSettings(updated);
if (changes.theme) {
injectThemeCSS(changes.theme.newValue);
}
}
} else if (designTweaksActive) {
stopDesignTweaks();
}
});
});
}
// Listen for system theme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', async () => {
const settings = await OR.loadSettings();
if (settings.enableDesignTweaks && settings.colorScheme === 'system') {
applyColorScheme('system');
}
});
init();
})();