Add widget to filter firewall rows in popup panel

This replaces the limited "visually enhance rows" togglers.
This commit is contained in:
Raymond Hill 2023-03-29 12:47:18 -04:00
parent 189bdd685f
commit 8d445e782d
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
3 changed files with 160 additions and 57 deletions

View File

@ -267,6 +267,7 @@ body.mobile.no-tooltips .toolRibbon .tool {
max-width: 460px; max-width: 460px;
min-width: var(--popup-firewall-min-width); min-width: var(--popup-firewall-min-width);
padding: 0; padding: 0;
position: relative;
overflow-y: auto; overflow-y: auto;
} }
:root.desktop #firewall { :root.desktop #firewall {
@ -275,18 +276,80 @@ body.mobile.no-tooltips .toolRibbon .tool {
:root.desktop body.vMin #firewall { :root.desktop body.vMin #firewall {
max-height: 100vh; max-height: 100vh;
} }
#firewall > * {
direction: ltr;
}
#firewall > section {
align-items: flex-start;
display: flex;
left: 0;
position: absolute;
z-index: 100;
}
#firewall > section .fa-icon {
color: var(--ink-4);
fill: var(--ink-4);
font-size: 150%;
padding: var(--popup-gap-thin);
}
#firewall > section:hover .fa-icon {
color: var(--ink-1);
fill: var(--ink-1);
}
#firewall.showBlocked > section .fa-icon,
#firewall.showAllowed > section .fa-icon,
#firewall.hideBlocked > section .fa-icon,
#firewall.hideAllowed > section .fa-icon,
#firewall.show3pScript > section .fa-icon,
#firewall.show3pFrame > section .fa-icon,
#firewall.hide3pScript > section .fa-icon,
#firewall.hide3pFrame > section .fa-icon {
color: rgb(var(--primary-70));
fill: rgb(var(--primary-70));
}
#firewall > section .filterExpressions {
background-color: var(--surface-0);
border: 1px solid var(--border-4);
display: none;
}
#firewall > section:hover .filterExpressions {
display: flex;
flex-direction: column;
}
#firewall > section .filterExpressions div {
border-bottom: 1px dotted #ddd;
padding: 0.25em;
}
#firewall > section .filterExpressions span {
cursor: default;
display: inline-flex;
margin: 0 0.25em 0 0;
padding: 0.5em;
white-space: nowrap;
border: 1px solid var(--surface-0);
}
#firewall > section .filterExpressions span:last-of-type {
margin: 0;
}
:root:not(.mobile) #firewall > section .filterExpressions span:not(.on):hover {
background-color: rgb(var(--primary-70) / 15%);
border: 1px solid rgb(var(--primary-70));
}
#firewall > section .filterExpressions span.on {
background-color: rgb(var(--primary-70) / 40%);
border: 1px solid rgb(var(--primary-70));
}
#firewall > div { #firewall > div {
border: 0; border: 0;
direction: ltr;
display: flex; display: flex;
margin: 0; margin: 0;
margin-top: 1px; margin-top: 1px;
padding: 0; padding: 0;
} }
#firewall > div:first-child { #firewall > div:first-of-type {
margin-top: 0; margin-top: 0;
} }
#firewall > div:first-child ~ div[data-des="*"] { #firewall > div:first-of-type ~ div[data-des="*"] {
display: none; display: none;
} }
#firewall:not(.expanded) > div.isSubdomain:not(.expandException):not(.isRootContext), #firewall:not(.expanded) > div.isSubdomain:not(.expandException):not(.isRootContext),
@ -302,12 +365,20 @@ body.mobile.no-tooltips .toolRibbon .tool {
padding: 0.4em 0; padding: 0.4em 0;
position: relative; position: relative;
} }
#firewall > div:first-of-type > span:first-of-type { #firewall > div:first-of-type span[data-i18n] {
cursor: pointer; cursor: pointer;
flex-direction: unset; flex-direction: unset;
flex-grow: 1;
}
#firewall > div:first-of-type span[data-i18n]::before {
color: var(--ink-3);
content: '+';
padding-right: 0.25em;
}
#firewall.expanded > div:first-of-type span[data-i18n]::before {
content: '\2012';
} }
#firewall > div > span:first-of-type { #firewall > div > span:first-of-type {
align-items: flex-end;
flex-direction: column; flex-direction: column;
flex-grow: 1; flex-grow: 1;
justify-content: flex-end; justify-content: flex-end;
@ -320,36 +391,18 @@ body.mobile.no-tooltips .toolRibbon .tool {
#firewall > div[data-des="*"] > span:first-of-type { #firewall > div[data-des="*"] > span:first-of-type {
flex-direction: row; flex-direction: row;
} }
#firewall > div[data-des="*"] > span:first-of-type > span.filter { #firewall.show3pScript:not(.show3pFrame) > div:not([data-des="*"]).is3p:not(.hasScript),
flex-grow: 1; #firewall.show3pFrame:not(.show3pScript) > div:not([data-des="*"]).is3p:not(.hasFrame),
padding-inline-start: 2px; #firewall.show3pScript.show3pFrame > div:not([data-des="*"]).is3p:not(.hasScript):not(.hasFrame),
-webkit-padding-start: 2px;
text-align: left;
}
#firewall:not(.has3pScript) > [data-type="3p-script"] .filter,
#firewall:not(.has3pFrame) > [data-type="3p-frame"] .filter {
display: none;
}
#firewall > [data-des="*"] .filter::after {
content: '\22EF';
}
#firewall.show3pScript > [data-type="3p-script"] .filter::after,
#firewall.show3pFrame > [data-type="3p-frame"] .filter::after {
content: '\2191';
}
#firewall.hide3pScript > [data-type="3p-script"] .filter::after,
#firewall.hide3pFrame > [data-type="3p-frame"] .filter::after {
content: '\2193';
}
#firewall.show3pScript > div:not([data-des="*"]):not(.hasScript),
#firewall.show3pScript > div:not([data-des="*"]):not(.is3p),
#firewall.hide3pScript > div:not([data-des="*"]).is3p.hasScript, #firewall.hide3pScript > div:not([data-des="*"]).is3p.hasScript,
#firewall.show3pFrame > div:not([data-des="*"]):not(.hasFrame),
#firewall.show3pFrame > div:not([data-des="*"]):not(.is3p),
#firewall.hide3pFrame > div:not([data-des="*"]).is3p.hasFrame, #firewall.hide3pFrame > div:not([data-des="*"]).is3p.hasFrame,
#firewall.show3pScript.show3pFrame > div:not([data-des="*"]).hasScript:not(.hasFrame), #firewall.showBlocked > div:not([data-des="*"]).is3p:not(.totalBlocked):not(.blocked),
#firewall.show3pScript.show3pFrame > div:not([data-des="*"]).hasFrame:not(.hasScript) { #firewall.showAllowed > div:not([data-des="*"]).is3p:not(.totalAllowed):not(.allowed),
opacity: 0.5; #firewall.hideBlocked > div:not([data-des="*"]).is3p.totalBlocked,
#firewall.hideBlocked > div:not([data-des="*"]).is3p.blocked,
#firewall.hideAllowed > div:not([data-des="*"]).is3p.totalAllowed,
#firewall.hideAllowed > div:not([data-des="*"]).is3p.allowed {
display: none;
} }
#firewall > div.isCname > span:first-of-type { #firewall > div.isCname > span:first-of-type {
color: var(--popup-cell-cname-ink); color: var(--popup-cell-cname-ink);
@ -389,14 +442,6 @@ body.mobile.no-tooltips .toolRibbon .tool {
color: var(--ink-3); color: var(--ink-3);
content: '\2026\A0'; content: '\2026\A0';
} }
#firewall > div:first-of-type > span:first-of-type::before {
color: var(--ink-3);
content: '+';
padding-right: 0.25em;
}
#firewall.expanded > div:first-of-type > span:first-of-type::before {
content: '\2012';
}
#firewall > div[data-des="*"] > span:nth-of-type(3), #firewall > div[data-des="*"] > span:nth-of-type(3),
#firewall > div.isSubdomain > span:nth-of-type(3), #firewall > div.isSubdomain > span:nth-of-type(3),
#firewall > div.isSubdomain.isRootContext > span:nth-of-type(3), #firewall > div.isSubdomain.isRootContext > span:nth-of-type(3),
@ -453,7 +498,7 @@ body.advancedUser #firewall > div > span:first-of-type {
body.advancedUser #firewall > div > span:nth-of-type(2) { body.advancedUser #firewall > div > span:nth-of-type(2) {
display: inline-flex; display: inline-flex;
} }
body.advancedUser #firewall > div:first-child ~ div[data-des="*"] { body.advancedUser #firewall > div:first-of-type ~ div[data-des="*"] {
display: flex; display: flex;
} }
body.advancedUser #firewall > div > span:first-of-type ~ span { body.advancedUser #firewall > div > span:first-of-type ~ span {

View File

@ -457,6 +457,75 @@ const reIP = /(\d|\])$/;
/******************************************************************************/ /******************************************************************************/
function filterFirewallRows() {
const firewallElem = qs$('#firewall');
const elems = qsa$('#firewall .filterExpressions span[data-expr]');
let not = false;
for ( const elem of elems ) {
const on = dom.cl.has(elem, 'on');
switch ( elem.dataset.expr ) {
case 'not':
not = on;
break;
case 'blocked':
dom.cl.toggle(firewallElem, 'showBlocked', !not && on);
dom.cl.toggle(firewallElem, 'hideBlocked', not && on);
break;
case 'allowed':
dom.cl.toggle(firewallElem, 'showAllowed', !not && on);
dom.cl.toggle(firewallElem, 'hideAllowed', not && on);
break;
case 'script':
dom.cl.toggle(firewallElem, 'show3pScript', !not && on);
dom.cl.toggle(firewallElem, 'hide3pScript', not && on);
break;
case 'frame':
dom.cl.toggle(firewallElem, 'show3pFrame', !not && on);
dom.cl.toggle(firewallElem, 'hide3pFrame', not && on);
break;
default:
break;
}
}
}
dom.on('#firewall .filterExpressions', 'click', 'span[data-expr]', ev => {
const target = ev.target;
dom.cl.toggle(target, 'on');
switch ( target.dataset.expr ) {
case 'blocked':
if ( dom.cl.has(target, 'on') === false ) { break; }
dom.cl.remove('#firewall .filterExpressions span[data-expr="allowed"]', 'on');
break;
case 'allowed':
if ( dom.cl.has(target, 'on') === false ) { break; }
dom.cl.remove('#firewall .filterExpressions span[data-expr="blocked"]', 'on');
break;
}
filterFirewallRows();
const elems = qsa$('#firewall .filterExpressions span[data-expr]');
const filters = Array.from(elems) .map(el => dom.cl.has(el, 'on') ? '1' : '0');
filters.unshift('00');
vAPI.localStorage.setItem('firewallFilters', filters.join(' '));
});
{
vAPI.localStorage.getItemAsync('firewallFilters').then(v => {
if ( v === null ) { return; }
const filters = v.split(' ');
if ( filters.shift() !== '00' ) { return; }
if ( filters.every(v => v === '0') ) { return; }
const elems = qsa$('#firewall .filterExpressions span[data-expr]');
for ( let i = 0; i < elems.length; i++ ) {
if ( filters[i] === '0' ) { continue; }
dom.cl.add(elems[i], 'on');
}
filterFirewallRows();
});
}
/******************************************************************************/
const renderPrivacyExposure = function() { const renderPrivacyExposure = function() {
const allDomains = {}; const allDomains = {};
let allDomainCount = 0; let allDomainCount = 0;
@ -1435,15 +1504,3 @@ dom.on('#revertRules', 'click', ( ) => { revertFirewallRules(); });
dom.on('a[href]', 'click', gotoURL); dom.on('a[href]', 'click', gotoURL);
/******************************************************************************/ /******************************************************************************/
// Toggle emphasis of rows with[out] 3rd-party scripts/frames
dom.on('#firewall > [data-type="3p-script"] .filter', 'click', ( ) => {
dom.cl.toggle('#firewall', 'show3pScript');
});
// Toggle visibility of rows with[out] 3rd-party frames
dom.on('#firewall > [data-type="3p-frame"] .filter', 'click', ( ) => {
dom.cl.toggle('#firewall', 'show3pFrame');
});
/******************************************************************************/

View File

@ -77,13 +77,14 @@
</div> </div>
</div> </div>
<div id="firewall" data-more="e"> <div id="firewall" data-more="e">
<div data-des="*" data-type="*"><span data-i18n="popupAnyRulePrompt"></span><span data-src="/" data-i18n-title="popupTipGlobalRules"> </span><span data-src="." data-i18n-title="popupTipLocalRules"> </span></div> <section><span class="fa-icon">filter</span><div class="filterExpressions"><div><span data-i18n="loggerRowFiltererBuiltinNot" data-expr="not">_</span><span data-i18n="loggerRowFiltererBuiltinBlocked" data-expr="blocked">_</span><span data-i18n="loggerRowFiltererBuiltinAllowed" data-expr="allowed">_</span></div><div><span data-i18n="loggerRowFiltererBuiltinNot" data-expr="not">_</span><span data-expr="script">&lt;script&gt;</span><span data-expr="frame">&lt;iframe&gt;</span></div></div></section>
<div data-des="*" data-type="*"><span data-i18n="popupAnyRulePrompt">_</span><span data-src="/" data-i18n-title="popupTipGlobalRules"> </span><span data-src="." data-i18n-title="popupTipLocalRules"> </span></div>
<div data-des="*" data-type="image"><span data-i18n="popupImageRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="image"><span data-i18n="popupImageRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
<div data-des="*" data-type="3p"><span data-i18n="popup3pAnyRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="3p"><span data-i18n="popup3pAnyRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
<div data-des="*" data-type="inline-script"><span data-i18n="popupInlineScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="inline-script"><span data-i18n="popupInlineScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
<div data-des="*" data-type="1p-script"><span data-i18n="popup1pScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="1p-script"><span data-i18n="popup1pScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
<div data-des="*" data-type="3p-script"><span><span class="filter" data-i18n-title="popup3pScriptFilterTip"></span><span data-i18n="popup3pScriptRulePrompt"></span></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="3p-script"><span data-i18n="popup3pScriptRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
<div data-des="*" data-type="3p-frame"><span><span class="filter" data-i18n-title="popup3pFrameFilterTip"></span><span data-i18n="popup3pFrameRulePrompt"></span></span><span data-src="/"> </span><span data-src="."> </span></div> <div data-des="*" data-type="3p-frame"><span data-i18n="popup3pFrameRulePrompt"></span><span data-src="/"> </span><span data-src="."> </span></div>
</div> </div>
<div id="firewall-vspacer"></div> <div id="firewall-vspacer"></div>
</div> </div>