-
diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index d9559c9ce..0b624c1d3 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -9,7 +9,7 @@ "32": "img/icon_32.png" }, "default_title": "uBlock Origin", - "default_popup": "popup.html" + "default_popup": "popup-fenix.html" }, "commands": { "launch-element-zapper": { diff --git a/platform/firefox/manifest.json b/platform/firefox/manifest.json index e47fbebe5..0ebc4a5ef 100644 --- a/platform/firefox/manifest.json +++ b/platform/firefox/manifest.json @@ -10,7 +10,7 @@ "32": "img/icon_32.png" }, "default_title": "uBlock Origin", - "default_popup": "popup.html" + "default_popup": "popup-fenix.html" }, "browser_specific_settings": { "gecko": { diff --git a/platform/opera/manifest.json b/platform/opera/manifest.json index 91400fcb8..649acd810 100644 --- a/platform/opera/manifest.json +++ b/platform/opera/manifest.json @@ -8,7 +8,7 @@ "16": "img/icon_16.png", "32": "img/icon_32.png" }, - "default_popup": "popup.html", + "default_popup": "popup-fenix.html", "default_title": "uBlock Origin" }, "commands": { diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 9bcd6c43e..648a6714d 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -201,7 +201,11 @@ }, "popupMoreButton_v2":{ "message":"More", - "description":"Label to be used to toggle overview panel" + "description":"Label to be used to show popup panel sections" + }, + "popupLessButton_v2":{ + "message":"Less", + "description":"Label to be used to hide popup panel sections" }, "popupTipGlobalRules":{ "message":"Global rules: this column is for rules which apply to all sites.", @@ -259,6 +263,10 @@ "message":"{{count}} out of {{total}}", "description":"appears in popup" }, + "popupVersion":{ + "message":"Version", + "description":"Example of use: Version 1.26.4" + }, "pickerCreate":{ "message":"Create", "description":"English: Create" diff --git a/src/css/popup-fenix.css b/src/css/popup-fenix.css index 9c7b5f071..fe490ace9 100644 --- a/src/css/popup-fenix.css +++ b/src/css/popup-fenix.css @@ -56,11 +56,11 @@ hr { align-items: stretch; display: flex; justify-content: space-between; - margin: var(--popup-default-gap) 0.5em; + margin: 0.5em 0.5em var(--popup-default-gap) 0.5em; } #switch { display: flex; - flex-grow: 2; + flex-grow: 3; justify-content: center; } #switch .fa-icon { @@ -71,10 +71,6 @@ hr { margin: 0; padding: 0; } -#switch .fa-icon:hover { - color: var(--popup-power-ink-hover); - fill: var(--popup-power-ink-hover); - } body.off #switch .fa-icon { color: var(--fg-0-20); fill: var(--fg-0-20); @@ -85,7 +81,7 @@ body.off #switch .fa-icon { box-sizing: border-box; display: flex; flex-direction: column; - flex-grow: 1; + flex-grow: 2; justify-content: space-evenly; } .rulesetTools [id] { @@ -93,7 +89,7 @@ body.off #switch .fa-icon { border: 1px solid #ddc; border-radius: 4px; cursor: pointer; - fill: #888; + fill: var(--default-ink-a50); flex-grow: 1; font-size: 2.2em; padding: 0; @@ -177,9 +173,23 @@ body.mobile.no-tooltips .toolRibbon .tool { visibility: visible; } -body:not(.dfEnabled) #moreButton .fa-icon { +.moreOrLess > span { + cursor: pointer; + } +#moreButton .fa-icon { transform: rotate(180deg); } +#lessButton { + text-align: right; + } +body[data-more="a b c d e"] #moreButton { + pointer-events: none; + visibility: hidden; + } +body[data-more=""] #lessButton { + pointer-events: none; + visibility: hidden; + } #tooltip { background-color: var(--bg-tooltip); @@ -224,9 +234,6 @@ body[dir="rtl"] #tooltip { text-align: right; --rule-cell-width: 5em; } -body:not(.dfEnabled) #firewall { - display: none; - } #firewall > div { border: 0; direction: ltr; @@ -246,11 +253,11 @@ body:not(.dfEnabled) #firewall { #firewall.expanded > div.isSubDomain.expandException:not(.isRootContext) { display: none; } -#firewall > div > span { +#firewall > div > span, +#actionSelector > #dynaCounts { background-color: var(--bg-popup-cell-2); border: none; box-sizing: border-box; - -moz-box-sizing: border-box; display: inline-flex; padding: 0.4em 0; position: relative; @@ -313,7 +320,8 @@ body:not(.dfEnabled) #firewall { #firewall.expanded > div:not(.expandException) > span:nth-of-type(3), #firewall:not(.expanded) > div.expandException > span:nth-of-type(3), #firewall:not(.expanded) > div.isDomain:not(.expandException) > span:nth-of-type(4), -#firewall.expanded > div.isDomain.expandException > span:nth-of-type(4) { +#firewall.expanded > div.isDomain.expandException > span:nth-of-type(4), +#actionSelector > #dynaCounts { display: inline-flex; justify-content: space-between; } @@ -423,15 +431,15 @@ body.advancedUser #firewall > div > span.ownRule, color: var(--default-surface); } body.advancedUser #firewall > div > span.allowRule.ownRule, -#actionSelector > #dynaAllow:hover { +:root.desktop #actionSelector > #dynaAllow:hover { background-color: var(--bg-popup-cell-allow-own); } body.advancedUser #firewall > div > span.blockRule.ownRule, -#actionSelector > #dynaBlock:hover { +:root.desktop #actionSelector > #dynaBlock:hover { background-color: var(--bg-popup-cell-block-own); } body.advancedUser #firewall > div > span.noopRule.ownRule, -#actionSelector > #dynaNoop:hover { +:root.desktop #actionSelector > #dynaNoop:hover { background-color: var(--bg-popup-cell-noop-own); } @@ -458,11 +466,8 @@ body.advancedUser #firewall > div > span.noopRule.ownRule, width: 33.5%; } #actionSelector > #dynaCounts { - align-items: center; background-color: transparent; - display: inline-flex; height: 100%; - justify-content: space-between; left: 0; pointer-events: none; position: absolute; @@ -488,6 +493,19 @@ body.advancedUser #firewall > div > span.noopRule.ownRule, :root body[data-ui~="+no-popups"] #no-popups { display: flex; } +body:not([data-more~="a"]) [data-more="a"], +body:not([data-more~="b"]) [data-more="b"], +body:not([data-more~="c"]) [data-more="c"], +body:not([data-more~="e"]) [data-more="e"] { + height: 0; + margin-bottom: 0; + margin-top: 0; + overflow-y: hidden; + visibility: hidden; + } +body:not([data-more~="d"]) [data-more="d"] { + display: none; + } /* mouse-driven devices */ :root.desktop { @@ -505,6 +523,13 @@ body.advancedUser #firewall > div > span.noopRule.ownRule, max-width: 300px; width: max-content; } +:root.desktop #switch .fa-icon:hover { + color: var(--popup-power-ink-hover); + fill: var(--popup-power-ink-hover); + } +:root.desktop .rulesetTools [id]:hover { + fill: var(--default-ink); + } :root.desktop #firewall { direction: rtl; flex-grow: 1; @@ -513,7 +538,7 @@ body.advancedUser #firewall > div > span.noopRule.ownRule, max-height: max(100vh, 600px); min-width: 360px; overflow-y: auto; - width: max-content; + width: min-content; } :root.desktop .tool { padding: 0.5em; @@ -521,3 +546,6 @@ body.advancedUser #firewall > div > span.noopRule.ownRule, :root.desktop .tool:hover { background-color: var(--button-surface); } +:root.desktop .moreOrLess > span:hover { + background-color: var(--button-surface); + } diff --git a/src/css/themes/default.css b/src/css/themes/default.css index 67542c030..44caba025 100644 --- a/src/css/themes/default.css +++ b/src/css/themes/default.css @@ -18,6 +18,7 @@ --ink-50: #291d4f; --ink-80: #20123a; --ink-80-a4: #20123a0a; + --ink-80-a50: #20123a88; --ink-90: #1d1133; --light-gray-10: #f9f9fb; --light-gray-30: #e0e0e6; @@ -53,6 +54,7 @@ --default-ink: var(--ink-80); --default-ink-a4: var(--ink-80-a4); + --default-ink-a50: var(--ink-80-a50); --default-surface: var(--light-gray-10); --bg-1: hsla(240, 20%, 98%, 1); diff --git a/src/js/background.js b/src/js/background.js index febc58d33..1ab8ff0a0 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -92,6 +92,8 @@ const µBlock = (( ) => { // jshint ignore:line ignoreGenericCosmeticFilters: vAPI.webextFlavor.soup.has('mobile'), largeMediaSize: 50, parseAllABPHideFilters: true, + popupPanelSections: 0b111, + popupPanelDisabledSections: 0, prefetchingDisabled: true, requestLogMaxEntries: 1000, showIconBadge: true, diff --git a/src/js/messaging.js b/src/js/messaging.js index 1561346bd..cb7e580f1 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -264,14 +264,14 @@ const getFirewallRules = function(srcHostname, desHostnames) { const popupDataFromTabId = function(tabId, tabTitle) { const tabContext = µb.tabContextManager.mustLookup(tabId); const rootHostname = tabContext.rootHostname; + const µbus = µb.userSettings; const r = { - advancedUserEnabled: µb.userSettings.advancedUserEnabled, + advancedUserEnabled: µbus.advancedUserEnabled, appName: vAPI.app.name, appVersion: vAPI.app.version, - colorBlindFriendly: µb.userSettings.colorBlindFriendly, + colorBlindFriendly: µbus.colorBlindFriendly, cosmeticFilteringSwitch: false, - dfEnabled: µb.userSettings.dynamicFilteringEnabled, - firewallPaneMinimized: µb.userSettings.firewallPaneMinimized, + firewallPaneMinimized: µbus.firewallPaneMinimized, globalAllowedRequestCount: µb.localSettings.allowedRequestCount, globalBlockedRequestCount: µb.localSettings.blockedRequestCount, fontSize: µb.hiddenSettings.popupFontSize, @@ -283,9 +283,11 @@ const popupDataFromTabId = function(tabId, tabTitle) { pageAllowedRequestCount: 0, pageBlockedRequestCount: 0, popupBlockedCount: 0, + popupPanelSections: µbus.popupPanelSections, + popupPanelDisabledSections: µbus.popupPanelDisabledSections, tabId: tabId, tabTitle: tabTitle, - tooltipsDisabled: µb.userSettings.tooltipsDisabled + tooltipsDisabled: µbus.tooltipsDisabled }; if ( µb.hiddenSettings.uiPopupConfig !== 'undocumented' ) { diff --git a/src/js/popup-fenix.js b/src/js/popup-fenix.js index 018c62d89..55774be0c 100644 --- a/src/js/popup-fenix.js +++ b/src/js/popup-fenix.js @@ -30,22 +30,21 @@ /******************************************************************************/ +/* let popupFontSize; vAPI.localStorage.getItemAsync('popupFontSize').then(value => { if ( typeof value !== 'string' || value === 'unset' ) { return; } document.body.style.setProperty('font-size', value); popupFontSize = value; }); +*/ // https://github.com/chrisaljoudi/uBlock/issues/996 // Experimental: mitigate glitchy popup UI: immediately set the firewall // pane visibility to its last known state. By default the pane is hidden. -let dfPaneVisibleStored; -vAPI.localStorage.getItemAsync('popupFirewallPane').then(value => { - dfPaneVisibleStored = value === true || value === 'true'; - if ( dfPaneVisibleStored ) { - document.body.classList.add('dfEnabled'); - } +vAPI.localStorage.getItemAsync('popupPanelSections').then(bits => { + if ( typeof bits !== 'number' ) { return; } + sectionBitsToAttribute(bits); }); /******************************************************************************/ @@ -485,21 +484,6 @@ const renderPopup = function() { uDom.nodeFromSelector('#no-remote-fonts .fa-icon-badge') .textContent = total ? Math.min(total, 99).toLocaleString() : ''; - // https://github.com/chrisaljoudi/uBlock/issues/470 - // This must be done here, to be sure the popup is resized properly - const dfPaneVisible = popupData.dfEnabled; - - // https://github.com/chrisaljoudi/uBlock/issues/1068 - // Remember the last state of the firewall pane. This allows to - // configure the popup size early next time it is opened, which means a - // less glitchy popup at open time. - if ( dfPaneVisible !== dfPaneVisibleStored ) { - dfPaneVisibleStored = dfPaneVisible; - vAPI.localStorage.setItem('popupFirewallPane', dfPaneVisibleStored); - } - - body.classList.toggle('dfEnabled', dfPaneVisible === true); - document.documentElement.classList.toggle( 'colorBlind', popupData.colorBlindFriendly === true @@ -508,7 +492,7 @@ const renderPopup = function() { setGlobalExpand(popupData.firewallPaneMinimized === false, true); // Build dynamic filtering pane only if in use - if ( dfPaneVisible ) { + if ( (popupData.popupPanelSections & ~popupData.popupPanelDisabledSections & 0b1000) !== 0 ) { buildAllFirewallRows(); } @@ -588,6 +572,7 @@ let renderOnce = function() { const body = document.body; +/* if ( popupData.fontSize !== popupFontSize ) { popupFontSize = popupData.fontSize; if ( popupFontSize !== 'unset' ) { @@ -598,11 +583,13 @@ let renderOnce = function() { vAPI.localStorage.removeItem('popupFontSize'); } } +*/ - // https://github.com/uBlockOrigin/uBlock-issues/issues/22 - if ( popupData.advancedUserEnabled !== true ) { - uDom('#firewall [title][data-src]').removeAttr('title'); - } + uDom.nodeFromId('version').textContent = popupData.appVersion; + + sectionBitsToAttribute( + popupData.popupPanelSections & ~popupData.popupPanelDisabledSections + ); if ( popupData.uiPopupConfig !== undefined ) { document.body.setAttribute('data-ui', popupData.uiPopupConfig); @@ -612,6 +599,11 @@ let renderOnce = function() { if ( popupData.tooltipsDisabled === true ) { uDom('[title]').removeAttr('title'); } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/22 + if ( popupData.advancedUserEnabled !== true ) { + uDom('#firewall [title][data-src]').removeAttr('title'); + } }; /******************************************************************************/ @@ -733,29 +725,71 @@ const gotoURL = function(ev) { /******************************************************************************/ -const toggleFirewallPane = function() { - popupData.dfEnabled = !popupData.dfEnabled; +// The popup panel is made of sections. Visiblity of sections can +// be toggle on/off. +const maxNumberOfSections = 5; + +const sectionBitsFromAttribute = function() { + const attr = document.body.dataset.more; + if ( attr === '' ) { return 0; } + let bits = 0; + for ( const c of attr.split(' ') ) { + bits |= 1 << (c.charCodeAt(0) - 97); + } + return bits; +}; + +const sectionBitsToAttribute = function(bits) { + const attr = []; + for ( let i = 0; i < maxNumberOfSections; i++ ) { + const bit = 1 << i; + if ( (bits & bit) === 0 ) { continue; } + attr.push(String.fromCharCode(97 + i)); + } + document.body.dataset.more = attr.join(' '); +}; + +const toggleSections = function(more) { + const mask = ~popupData.popupPanelDisabledSections; + let currentBits = sectionBitsFromAttribute(); + let newBits = currentBits; + for ( let i = 0; i < maxNumberOfSections; i++ ) { + const bit = 1 << (more ? i : maxNumberOfSections - i - 1); + if ( (mask & bit) === 0 ) { continue; } + if ( more ) { + newBits |= bit; + } else { + newBits &= ~bit; + } + if ( newBits !== currentBits ) { break; } + } + if ( newBits === currentBits ) { return; } + + sectionBitsToAttribute(newBits); + + popupData.popupPanelSections = newBits; messaging.send('popupPanel', { what: 'userSettings', - name: 'dynamicFilteringEnabled', - value: popupData.dfEnabled, + name: 'popupPanelSections', + value: newBits, }); // https://github.com/chrisaljoudi/uBlock/issues/996 - // Remember the last state of the firewall pane. This allows to - // configure the popup size early next time it is opened, which means a - // less glitchy popup at open time. - dfPaneVisibleStored = popupData.dfEnabled; - vAPI.localStorage.setItem('popupFirewallPane', dfPaneVisibleStored); + // Remember the last state of the firewall pane. This allows to + // configure the popup size early next time it is opened, which means a + // less glitchy popup at open time. + vAPI.localStorage.setItem('popupPanelSections', newBits); // Dynamic filtering pane may not have been built yet - document.body.classList.toggle('dfEnabled', popupData.dfEnabled); - if ( popupData.dfEnabled && dfPaneBuilt === false ) { + if ( (newBits & 0b1000) !== 0 && dfPaneBuilt === false ) { buildAllFirewallRows(); } }; +uDom('#moreButton').on('click', ( ) => { toggleSections(true); }); +uDom('#lessButton').on('click', ( ) => { toggleSections(false); }); + /******************************************************************************/ const mouseenterCellHandler = function() { @@ -1138,7 +1172,6 @@ const getPopupData = async function(tabId) { uDom('#switch').on('click', toggleNetFilteringSwitch); uDom('#gotoZap').on('click', gotoZap); uDom('#gotoPick').on('click', gotoPick); -uDom('#moreButton').on('click', toggleFirewallPane); uDom('.hnSwitch').on('click', ev => { toggleHostnameSwitch(ev); }); uDom('#saveRules').on('click', saveFirewallRules); uDom('#revertRules').on('click', ( ) => { revertFirewallRules(); }); diff --git a/src/js/popup.js b/src/js/popup.js index 266036a4d..3be9676c0 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -506,7 +506,7 @@ const renderPopup = function() { // https://github.com/chrisaljoudi/uBlock/issues/470 // This must be done here, to be sure the popup is resized properly - const dfPaneVisible = popupData.dfEnabled; + const dfPaneVisible = (popupData.popupPanelSections & 0b1000) !== 0; // https://github.com/chrisaljoudi/uBlock/issues/1068 // Remember the last state of the firewall pane. This allows to @@ -517,10 +517,7 @@ const renderPopup = function() { vAPI.localStorage.setItem('popupFirewallPane', dfPaneVisibleStored); } - uDom.nodeFromId('panes').classList.toggle( - 'dfEnabled', - dfPaneVisible === true - ); + uDom.nodeFromId('panes').classList.toggle('dfEnabled', dfPaneVisible === true); document.documentElement.classList.toggle( 'colorBlind', @@ -795,24 +792,24 @@ const gotoURL = function(ev) { /******************************************************************************/ const toggleFirewallPane = function() { - popupData.dfEnabled = !popupData.dfEnabled; + popupData.popupPanelSections = popupData.popupPanelSections ^ 0b1000; messaging.send('popupPanel', { what: 'userSettings', - name: 'dynamicFilteringEnabled', - value: popupData.dfEnabled, + name: 'popupPanelSections', + value: popupData.popupPanelSections | 0b0111, }); // https://github.com/chrisaljoudi/uBlock/issues/996 // Remember the last state of the firewall pane. This allows to // configure the popup size early next time it is opened, which means a // less glitchy popup at open time. - dfPaneVisibleStored = popupData.dfEnabled; + dfPaneVisibleStored = (popupData.popupPanelSections & 0b1000) !== 0; vAPI.localStorage.setItem('popupFirewallPane', dfPaneVisibleStored); // Dynamic filtering pane may not have been built yet - uDom.nodeFromId('panes').classList.toggle('dfEnabled', popupData.dfEnabled); - if ( popupData.dfEnabled && dfPaneBuilt === false ) { + uDom.nodeFromId('panes').classList.toggle('dfEnabled', dfPaneVisibleStored); + if ( dfPaneVisibleStored && dfPaneBuilt === false ) { buildAllFirewallRows(); } }; @@ -1076,7 +1073,7 @@ const toggleHostnameSwitch = async function(ev) { hostname: popupData.pageHostname, state: target.classList.contains('on'), tabId: popupData.tabId, - persist: popupData.dfEnabled === false || ev.ctrlKey || ev.metaKey, + persist: (popupData.popupPanelSections & 0b1000) === 0 || ev.ctrlKey || ev.metaKey, }); cachePopupData(response); diff --git a/src/js/start.js b/src/js/start.js index 79f8b3f96..7e2b3f74a 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -114,6 +114,15 @@ const onVersionReady = function(lastVersion) { µb.saveHostnameSwitches(); } + // Configure new popup panel according to classic popup panel + // configuration. + if ( lastVersionInt !== 0 && lastVersionInt <= 1026003014 ) { + µb.userSettings.popupPanelSections = + µb.userSettings.dynamicFilteringEnabled === true ? 0b1111 : 0b0111; + µb.userSettings.dynamicFilteringEnabled = undefined; + µb.saveUserSettings(); + } + vAPI.storage.set({ version: vAPI.app.version }); }; @@ -356,14 +365,16 @@ if ( browser.browserAction instanceof Object && browser.browserAction.setPopup instanceof Function ) { - let uiFlavor = µb.hiddenSettings.uiFlavor; - if ( uiFlavor === 'unset' && vAPI.webextFlavor.soup.has('mobile') ) { - uiFlavor = 'fenix'; - } - if ( uiFlavor !== 'unset' && /\w+/.test(uiFlavor) ) { - browser.browserAction.setPopup({ - popup: vAPI.getURL(`popup-${uiFlavor}.html`) - }); + const env = vAPI.webextFlavor; + if ( + µb.hiddenSettings.uiFlavor === 'classic' || ( + µb.hiddenSettings.uiFlavor === 'unset' && ( + env.soup.has('chromium') && env.major < 66 || + env.soup.has('firefox') && env.major < 68 + ) + ) + ) { + browser.browserAction.setPopup({ popup: vAPI.getURL('popup.html') }); } } diff --git a/src/js/ublock.js b/src/js/ublock.js index 6dd2a792c..79dc7fd52 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -331,7 +331,7 @@ const matchBucket = function(url, hostname, bucket, start) { switch ( name ) { case 'advancedUserEnabled': if ( value === true ) { - us.dynamicFilteringEnabled = true; + us.popupPanelSections = 0b1111; } break; case 'autoUpdate': diff --git a/src/popup-fenix.html b/src/popup-fenix.html index 0c080b4bf..6fd77438b 100644 --- a/src/popup-fenix.html +++ b/src/popup-fenix.html @@ -11,7 +11,7 @@