[mv3] Add textarea to list/edit trusted sites

Related issue:
https://github.com/uBlockOrigin/uBOL-home/issues/29
This commit is contained in:
Raymond Hill 2023-11-28 21:13:44 -05:00
parent 2bd2e6a079
commit d7acad6c90
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
6 changed files with 120 additions and 7 deletions

View File

@ -143,6 +143,10 @@
"message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher webpage resources usage.", "message": "Advanced network filtering plus specific and generic extended filtering from selected filter lists.\n\nRequires broad permission to read and modify data on all websites.\n\nGeneric extended filtering may cause higher webpage resources usage.",
"description": "This describes the 'complete' filtering mode" "description": "This describes the 'complete' filtering mode"
}, },
"noFilteringModeDescription": {
"message": "List of hostnames for which no filtering will take place",
"description": "A short description for the editable field which lists trusted sites"
},
"behaviorSectionLabel": { "behaviorSectionLabel": {
"message": "Behavior", "message": "Behavior",
"description": "The header text for the 'Behavior' section" "description": "The header text for the 'Behavior' section"

View File

@ -64,6 +64,16 @@ p {
width: calc(240px / 2); width: calc(240px / 2);
} }
h3[data-i18n="filteringMode0Name"]::first-letter {
text-transform: capitalize;
}
#trustedSites {
box-sizing: border-box;
height: 6rem;
resize: vertical;
width: 100%;
}
#lists { #lists {
margin: 0.5em 0 0 0; margin: 0.5em 0 0 0;
padding: 0; padding: 0;

View File

@ -12,7 +12,6 @@
<link rel="stylesheet" href="css/dashboard-common.css"> <link rel="stylesheet" href="css/dashboard-common.css">
<link rel="stylesheet" href="css/filtering-mode.css"> <link rel="stylesheet" href="css/filtering-mode.css">
<link rel="stylesheet" href="css/settings.css"> <link rel="stylesheet" href="css/settings.css">
<link rel="stylesheet" href="css/about.css">
<link rel="shortcut icon" type="image/png" href="img/icon_64.png"/> <link rel="shortcut icon" type="image/png" href="img/icon_64.png"/>
</head> </head>
@ -20,7 +19,7 @@
<body data-pane="settings"> <body data-pane="settings">
<!-- -------- --> <!-- -------- -->
<div id="dashboard-nav"> <div id="dashboard-nav">
<span class="logo"><img data-i18n-title="extName" src="img/ublock.svg"></span><!-- <span class="logo"><img data-i18n-title="extName" src="img/ublock.svg" alt="uBO Lite"></span><!--
--><button class="tabButton" type="button" data-pane="settings" data-i18n="settingsPageName" tabindex="0"></button><!-- --><button class="tabButton" type="button" data-pane="settings" data-i18n="settingsPageName" tabindex="0"></button><!--
--><button class="tabButton" type="button" data-pane="about" data-i18n="aboutPageName" tabindex="0"></button> --><button class="tabButton" type="button" data-pane="about" data-i18n="aboutPageName" tabindex="0"></button>
</div> </div>
@ -83,6 +82,13 @@
</div> </div>
</div> </div>
<div>
<h3 data-i18n="filteringMode0Name"></h3>
<p data-i18n="noFilteringModeDescription">_</p>
<p><textarea id="trustedSites" spellcheck="false"></textarea>
</p>
</div>
<div> <div>
<h3 data-i18n="behaviorSectionLabel"></h3> <h3 data-i18n="behaviorSectionLabel"></h3>
<p><label id="autoReload" data-i18n="autoReloadLabel"><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>_</label> <p><label id="autoReload" data-i18n="autoReloadLabel"><span class="input checkbox"><input type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span>_</label>

View File

@ -51,6 +51,8 @@ import {
setFilteringMode, setFilteringMode,
getDefaultFilteringMode, getDefaultFilteringMode,
setDefaultFilteringMode, setDefaultFilteringMode,
getTrustedSites,
setTrustedSites,
syncWithBrowserPermissions, syncWithBrowserPermissions,
} from './mode-manager.js'; } from './mode-manager.js';
@ -151,8 +153,7 @@ function onMessage(request, sender, callback) {
}).catch(reason => { }).catch(reason => {
console.log(reason); console.log(reason);
}); });
callback(); return false;
return;
} }
default: default:
@ -181,16 +182,19 @@ function onMessage(request, sender, callback) {
case 'getOptionsPageData': { case 'getOptionsPageData': {
Promise.all([ Promise.all([
getDefaultFilteringMode(), getDefaultFilteringMode(),
getTrustedSites(),
getRulesetDetails(), getRulesetDetails(),
dnr.getEnabledRulesets(), dnr.getEnabledRulesets(),
]).then(results => { ]).then(results => {
const [ const [
defaultFilteringMode, defaultFilteringMode,
trustedSites,
rulesetDetails, rulesetDetails,
enabledRulesets, enabledRulesets,
] = results; ] = results;
callback({ callback({
defaultFilteringMode, defaultFilteringMode,
trustedSites: Array.from(trustedSites),
enabledRulesets, enabledRulesets,
maxNumberOfEnabledRulesets: dnr.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS, maxNumberOfEnabledRulesets: dnr.MAX_NUMBER_OF_ENABLED_STATIC_RULESETS,
rulesetDetails: Array.from(rulesetDetails.values()), rulesetDetails: Array.from(rulesetDetails.values()),
@ -262,6 +266,21 @@ function onMessage(request, sender, callback) {
return true; return true;
} }
case 'setTrustedSites':
setTrustedSites(request.hostnames).then(( ) => {
registerInjectables();
return Promise.all([
getDefaultFilteringMode(),
getTrustedSites(),
]);
}).then(results => {
callback({
defaultFilteringMode: results[0],
trustedSites: Array.from(results[1]),
});
});
return true;
default: default:
break; break;
} }

View File

@ -354,6 +354,35 @@ export function setDefaultFilteringMode(afterLevel) {
/******************************************************************************/ /******************************************************************************/
export async function getTrustedSites() {
const filteringModes = await getFilteringModeDetails();
return filteringModes.none;
}
export async function setTrustedSites(hostnames) {
const filteringModes = await getFilteringModeDetails();
const { none } = filteringModes;
const hnSet = new Set(hostnames);
let modified = false;
for ( const hn of none ) {
if ( hnSet.has(hn) ) {
hnSet.delete(hn);
} else {
none.delete(hn);
modified = true;
}
}
for ( const hn of hnSet ) {
const level = applyFilteringMode(filteringModes, hn, MODE_NONE);
if ( level !== MODE_NONE ) { continue; }
modified = true;
}
if ( modified === false ) { return; }
return writeFilteringModeDetails(filteringModes);
}
/******************************************************************************/
export async function syncWithBrowserPermissions() { export async function syncWithBrowserPermissions() {
const [ permissions, beforeMode ] = await Promise.all([ const [ permissions, beforeMode ] = await Promise.all([
browser.permissions.getAll(), browser.permissions.getAll(),

View File

@ -24,6 +24,7 @@
import { browser, sendMessage, localRead, localWrite } from './ext.js'; import { browser, sendMessage, localRead, localWrite } from './ext.js';
import { i18n$, i18n } from './i18n.js'; import { i18n$, i18n } from './i18n.js';
import { dom, qs$, qsa$ } from './dom.js'; import { dom, qs$, qsa$ } from './dom.js';
import punycode from './punycode.js';
/******************************************************************************/ /******************************************************************************/
@ -204,8 +205,6 @@ function renderFilterLists(soft = false) {
} }
dom.remove('#lists .listEntries .listEntry.discard'); dom.remove('#lists .listEntries .listEntry.discard');
renderWidgets();
} }
/******************************************************************************/ /******************************************************************************/
@ -216,7 +215,13 @@ const renderWidgets = function() {
} }
const defaultLevel = cachedRulesetData.defaultFilteringMode; const defaultLevel = cachedRulesetData.defaultFilteringMode;
if ( defaultLevel !== 0 ) {
qs$(`.filteringModeCard input[type="radio"][value="${defaultLevel}"]`).checked = true; qs$(`.filteringModeCard input[type="radio"][value="${defaultLevel}"]`).checked = true;
} else {
dom.prop('.filteringModeCard input[type="radio"]', 'checked', false);
}
renderTrustedSites(cachedRulesetData.trustedSites);
qs$('#autoReload input[type="checkbox"').checked = cachedRulesetData.autoReload; qs$('#autoReload input[type="checkbox"').checked = cachedRulesetData.autoReload;
@ -295,6 +300,45 @@ dom.on('#autoReload input[type="checkbox"', 'change', ev => {
/******************************************************************************/ /******************************************************************************/
let trustedSitesHash = '';
function renderTrustedSites(hostnames) {
const textarea = qs$('#trustedSites');
trustedSitesHash = hostnames.sort().join('\n');
textarea.value = hostnames.map(hn => punycode.toUnicode(hn)).join('\n');
if ( textarea.value !== '' ) {
textarea.value += '\n';
}
}
function changeTrustedSites() {
const textarea = qs$('#trustedSites');
const hostnames = textarea.value.split(/\s/).map(hn => {
try {
return punycode.toASCII(
(new URL(`https://${hn}/`)).hostname
);
} catch(_) {
}
return '';
}).filter(hn => hn !== '').sort();
if ( hostnames.join('\n') === trustedSitesHash ) { return; }
sendMessage({
what: 'setTrustedSites',
hostnames,
}).then(response => {
cachedRulesetData.defaultFilteringMode = response.defaultFilteringMode;
cachedRulesetData.trustedSites = response.trustedSites;
renderWidgets();
});
}
dom.on('#trustedSites', 'blur', changeTrustedSites);
self.addEventListener('beforeunload', changeTrustedSites);
/******************************************************************************/
async function applyEnabledRulesets() { async function applyEnabledRulesets() {
const enabledRulesets = []; const enabledRulesets = [];
for ( const liEntry of qsa$('#lists .listEntry[data-listkey]') ) { for ( const liEntry of qsa$('#lists .listEntry[data-listkey]') ) {
@ -385,6 +429,7 @@ sendMessage({
cachedRulesetData.rulesetDetails.forEach(rule => rulesetMap.set(rule.id, rule)); cachedRulesetData.rulesetDetails.forEach(rule => rulesetMap.set(rule.id, rule));
try { try {
renderFilterLists(); renderFilterLists();
renderWidgets();
} catch(ex) { } catch(ex) {
} }
}).catch(reason => { }).catch(reason => {