From 088bd45069228f0297e3f6daf414d43c8c65e9b3 Mon Sep 17 00:00:00 2001 From: Joel Brock Date: Thu, 23 Apr 2026 09:01:23 -0700 Subject: [PATCH] =?UTF-8?q?feat:=20popup=20settings=20logic=20=E2=80=94=20?= =?UTF-8?q?load,=20save,=20presets,=20export/import/reset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- popup/popup.js | 243 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 popup/popup.js diff --git a/popup/popup.js b/popup/popup.js new file mode 100644 index 0000000..99a4bdd --- /dev/null +++ b/popup/popup.js @@ -0,0 +1,243 @@ +// Outlook Relook — Popup Settings Logic + +(function () { + 'use strict'; + + // We need access to DEFAULTS and DENSITY_PRESETS from settings-defaults.js, + // but popup runs in its own context. Duplicate the defaults here. + // (Content scripts and popup don't share a JS context.) + + var DEFAULTS = { + theme: 'swiss', + colorScheme: 'system', + accentColor: '', + densityPreset: 'compact', + compactTopBar: true, + compactCommandBar: true, + compactMessageList: true, + compactReadingPane: true, + compactFolderPane: true, + narrowDateColumn: true, + compressComposeToolbar: true, + readingPaneMaxWidth: true, + hideCopilot: true, + hideSuggestedReplies: true, + hidePromoBanners: true, + hideFocusedOtherTabs: true, + hideSidebarAppIcons: false, + hideGroupsSection: false, + hideMyDayButtons: true, + hideSenderAvatars: false, + hideFeatureDiscovery: true, + hideVivaInsights: true, + hideUnreadOtherBanner: true, + hideActivityFeed: true, + unreadDistinction: true, + previewOwnLine: false, + normalizeFontWeight: true, + darkModeEmailFix: true, + messageListFontSize: 'medium', + autoCollapseRibbon: true, + rememberSidebarState: true, + suppressContactHover: true, + autoAdvanceAfterDelete: true, + autoDismissToasts: '5', + toastPosition: 'top-right', + stickyReplyBar: true, + autoResizeCompose: true, + throttleNotifications: false, + keyboardMultiSelect: true, + markAllReadButton: true, + quickFolderJump: true, + }; + + var DENSITY_PRESETS = { + comfortable: { + compactTopBar: false, + compactCommandBar: false, + compactMessageList: false, + compactReadingPane: false, + compactFolderPane: false, + narrowDateColumn: false, + compressComposeToolbar: false, + readingPaneMaxWidth: true, + }, + compact: { + compactTopBar: true, + compactCommandBar: true, + compactMessageList: true, + compactReadingPane: true, + compactFolderPane: true, + narrowDateColumn: true, + compressComposeToolbar: true, + readingPaneMaxWidth: true, + }, + 'ultra-compact': { + compactTopBar: true, + compactCommandBar: true, + compactMessageList: true, + compactReadingPane: true, + compactFolderPane: true, + narrowDateColumn: true, + compressComposeToolbar: true, + readingPaneMaxWidth: true, + }, + }; + + // --- Load settings and populate UI --- + function loadUI() { + chrome.storage.sync.get(DEFAULTS, function (settings) { + // Checkboxes + var checkboxes = document.querySelectorAll('input[type="checkbox"][data-setting]'); + for (var i = 0; i < checkboxes.length; i++) { + checkboxes[i].checked = !!settings[checkboxes[i].dataset.setting]; + } + + // Selects + var selects = document.querySelectorAll('select[data-setting]'); + for (var j = 0; j < selects.length; j++) { + selects[j].value = settings[selects[j].dataset.setting] || ''; + } + + // Radio groups + var radioGroups = document.querySelectorAll('.or-radio-group[data-setting]'); + for (var k = 0; k < radioGroups.length; k++) { + var key = radioGroups[k].dataset.setting; + var radio = radioGroups[k].querySelector('input[value="' + settings[key] + '"]'); + if (radio) radio.checked = true; + } + + // Color picker + var colorPicker = document.querySelector('input[type="color"][data-setting]'); + if (colorPicker) { + colorPicker.value = settings.accentColor || '#1976d2'; + } + + // Version + var manifest = chrome.runtime.getManifest(); + document.getElementById('version').textContent = 'v' + manifest.version; + }); + } + + // --- Save a single setting --- + function saveSetting(key, value) { + var obj = {}; + obj[key] = value; + chrome.storage.sync.set(obj); + } + + // --- Section accordion --- + var sectionHeaders = document.querySelectorAll('.or-section-header'); + for (var s = 0; s < sectionHeaders.length; s++) { + sectionHeaders[s].addEventListener('click', function () { + this.parentElement.classList.toggle('open'); + }); + } + + // --- Checkbox change handlers --- + var checkboxes = document.querySelectorAll('input[type="checkbox"][data-setting]'); + for (var c = 0; c < checkboxes.length; c++) { + checkboxes[c].addEventListener('change', function () { + saveSetting(this.dataset.setting, this.checked); + }); + } + + // --- Select change handlers --- + var selects = document.querySelectorAll('select[data-setting]'); + for (var sl = 0; sl < selects.length; sl++) { + selects[sl].addEventListener('change', function () { + var settingKey = this.dataset.setting; + var value = this.value; + saveSetting(settingKey, value); + + // Density preset: apply to individual toggles + if (settingKey === 'densityPreset' && DENSITY_PRESETS[value]) { + var preset = DENSITY_PRESETS[value]; + chrome.storage.sync.set(preset); + // Update checkboxes in the UI + var toggleKeys = Object.keys(preset); + for (var p = 0; p < toggleKeys.length; p++) { + var checkbox = document.getElementById(toggleKeys[p]); + if (checkbox) checkbox.checked = preset[toggleKeys[p]]; + } + } + }); + } + + // --- Radio group change handlers --- + var radioGroups = document.querySelectorAll('.or-radio-group[data-setting]'); + for (var r = 0; r < radioGroups.length; r++) { + var groupKey = radioGroups[r].dataset.setting; + var radios = radioGroups[r].querySelectorAll('input[type="radio"]'); + for (var ri = 0; ri < radios.length; ri++) { + (function (gk) { + radios[ri].addEventListener('change', function () { + if (this.checked) saveSetting(gk, this.value); + }); + })(groupKey); + } + } + + // --- Color picker change handler --- + var colorPickers = document.querySelectorAll('input[type="color"][data-setting]'); + for (var cp = 0; cp < colorPickers.length; cp++) { + colorPickers[cp].addEventListener('input', function () { + saveSetting(this.dataset.setting, this.value); + }); + } + + // --- Export settings --- + document.getElementById('exportBtn').addEventListener('click', function () { + chrome.storage.sync.get(DEFAULTS, function (settings) { + var blob = new Blob([JSON.stringify(settings, null, 2)], { type: 'application/json' }); + var url = URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = url; + a.download = 'outlook-relook-settings.json'; + a.click(); + URL.revokeObjectURL(url); + }); + }); + + // --- Import settings --- + document.getElementById('importBtn').addEventListener('click', function () { + document.getElementById('importFile').click(); + }); + + document.getElementById('importFile').addEventListener('change', function (e) { + var file = e.target.files[0]; + if (!file) return; + + var reader = new FileReader(); + reader.onload = function (event) { + try { + var imported = JSON.parse(event.target.result); + // Only import known keys + var cleaned = {}; + var defaultKeys = Object.keys(DEFAULTS); + for (var i = 0; i < defaultKeys.length; i++) { + if (defaultKeys[i] in imported) cleaned[defaultKeys[i]] = imported[defaultKeys[i]]; + } + chrome.storage.sync.set(cleaned, function () { + loadUI(); + }); + } catch (err) { + alert('Invalid settings file.'); + } + }; + reader.readAsText(file); + e.target.value = ''; + }); + + // --- Reset to defaults --- + document.getElementById('resetBtn').addEventListener('click', function () { + if (confirm('Reset all settings to defaults?')) { + chrome.storage.sync.set(DEFAULTS, function () { + loadUI(); + }); + } + }); + + // --- Init --- + loadUI(); +})();