1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-11-16 15:33:38 +01:00

[mv3] Add a _chat_ icon in popup panel to report filter issues

Just the same as with uBO, but for uBOL.
This commit is contained in:
Raymond Hill 2024-09-28 14:08:42 -04:00
parent dcb86e3667
commit 560def639f
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
10 changed files with 371 additions and 20 deletions

View File

@ -31,6 +31,10 @@
"message": "filtering mode", "message": "filtering mode",
"description": "Label in the popup panel for the current filtering mode" "description": "Label in the popup panel for the current filtering mode"
}, },
"popupTipReport": {
"message": "Report an issue on this website",
"description": "Tooltip used for the 'chat' icon in the panel"
},
"popupTipDashboard": { "popupTipDashboard": {
"message": "Open the dashboard", "message": "Open the dashboard",
"description": "English: Click to open the dashboard" "description": "English: Click to open the dashboard"
@ -99,6 +103,70 @@
"message": "External dependencies (GPLv3-compatible):", "message": "External dependencies (GPLv3-compatible):",
"description": "Shown in the About pane" "description": "Shown in the About pane"
}, },
"supportS6H": {
"message": "Report a filter issue",
"description": "Header of 'Report a filter issue' section in Support pane"
},
"supportS3P1": {
"message": "Report filter issues with specific websites to the <span data-url=\"https://github.com/uBlockOrigin/uAssets/issues?q=is%3Aissue\"><code>uBlockOrigin/uAssets</code> issue tracker</span>. <u>Requires a GitHub account.</u>",
"description": "First paragraph of 'Filter issues' section in Support pane"
},
"supportS6P1S1": {
"message": "To avoid burdening volunteers with duplicate reports, please verify that the issue has not already been reported.",
"description": "A paragraph in the filter issue reporter section"
},
"supportFindSpecificButton": {
"message": "Find similar reports",
"description": "A clickable link in the filter issue reporter section"
},
"supportS6URL": {
"message": "Address of the webpage:",
"description": "Label for the URL of the page"
},
"supportS6Select1": {
"message": "The webpage…",
"description": "Label for widget to select type of issue"
},
"supportS6Select1Option0": {
"message": "-- Pick an entry --",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option1": {
"message": "Shows ads or ad leftovers",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option2": {
"message": "Has overlays or other nuisances",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option3": {
"message": "Detects uBO Lite",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option4": {
"message": "Has privacy-related issues",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option5": {
"message": "Malfunctions when uBO Lite is enabled",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option6": {
"message": "Opens unwanted tabs or windows",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Select1Option7": {
"message": "Leads to badware, phishing",
"description": "An entry in the widget used to select the type of issue"
},
"supportS6Checkbox1": {
"message": "Label the webpage as “NSFW” (<a href=\"https://wikipedia.org/wiki/Not_safe_for_work\">“Not Safe For Work”</a>)",
"description": "A checkbox to use for NSFW sites"
},
"supportReportSpecificButton": {
"message": "Create new report",
"description": "Text for button which open an external webpage in Support pane"
},
"firstRunSectionLabel": { "firstRunSectionLabel": {
"message": "Welcome", "message": "Welcome",
"description": "The header text for the welcome message section" "description": "The header text for the welcome message section"

View File

@ -1,3 +1,14 @@
body {
align-items: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
padding: 0 var(--default-gap-xxsmall);
}
body > * {
width: min(640px, 100%);
}
h2, h3 { h2, h3 {
margin: 1em 0; margin: 1em 0;
} }
@ -7,9 +18,11 @@ h2 {
h3 { h3 {
font-size: 16px; font-size: 16px;
} }
a { a {
text-decoration: none; text-decoration: none;
} }
.fa-icon.info { .fa-icon.info {
color: var(--info0-ink); color: var(--info0-ink);
fill: var(--info0-ink); fill: var(--info0-ink);

View File

@ -1,12 +1,3 @@
body {
align-items: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
body > * {
width: min(640px, 100%);
}
#dashboard-nav { #dashboard-nav {
background-color: var(--surface-1); background-color: var(--surface-1);
border: 0; border: 0;

View File

@ -22,10 +22,6 @@ p {
white-space: pre-line; white-space: pre-line;
} }
section > div {
padding: 0 var(--default-gap-xxsmall);
}
#showBlockedCount:has(input[type="checkbox"][disabled]) { #showBlockedCount:has(input[type="checkbox"][disabled]) {
opacity: 0.5; opacity: 0.5;
} }

View File

@ -145,6 +145,36 @@ async function onPermissionsRemoved() {
/******************************************************************************/ /******************************************************************************/
async function gotoURL(url, type) {
const pageURL = new URL(url, runtime.getURL('/'));
const tabs = await browser.tabs.query({
url: pageURL.href,
windowType: type !== 'popup' ? 'normal' : 'popup'
});
if ( Array.isArray(tabs) && tabs.length !== 0 ) {
const { windowId, id } = tabs[0];
return Promise.all([
browser.windows.update(windowId, { focused: true }),
browser.tabs.update(id, { active: true }),
]);
}
if ( type === 'popup' ) {
return windows.create({
type: 'popup',
url: pageURL.href,
});
}
return browser.tabs.create({
active: true,
url: pageURL.href,
});
}
/******************************************************************************/
function onMessage(request, sender, callback) { function onMessage(request, sender, callback) {
// Does not require trusted origin. // Does not require trusted origin.
@ -265,6 +295,10 @@ function onMessage(request, sender, callback) {
return true; return true;
} }
case 'gotoURL':
gotoURL(request.url, request.type);
break;
case 'setFilteringMode': { case 'setFilteringMode': {
getFilteringMode(request.hostname).then(actualLevel => { getFilteringMode(request.hostname).then(actualLevel => {
if ( request.level === actualLevel ) { return actualLevel; } if ( request.level === actualLevel ) { return actualLevel; }
@ -276,6 +310,13 @@ function onMessage(request, sender, callback) {
return true; return true;
} }
case 'getDefaultFilteringMode': {
getDefaultFilteringMode().then(level => {
callback(level);
});
return true;
}
case 'setDefaultFilteringMode': { case 'setDefaultFilteringMode': {
getDefaultFilteringMode().then(beforeLevel => getDefaultFilteringMode().then(beforeLevel =>
setDefaultFilteringMode(request.level).then(afterLevel => setDefaultFilteringMode(request.level).then(afterLevel =>

View File

@ -261,12 +261,6 @@ dom.on('#lessButton', 'click', ( ) => {
/******************************************************************************/ /******************************************************************************/
dom.on('[data-i18n-title="popupTipDashboard"]', 'click', ev => {
if ( ev.isTrusted !== true ) { return; }
if ( ev.button !== 0 ) { return; }
runtime.openOptionsPage();
});
dom.on('#showMatchedRules', 'click', ev => { dom.on('#showMatchedRules', 'click', ev => {
if ( ev.isTrusted !== true ) { return; } if ( ev.isTrusted !== true ) { return; }
if ( ev.button !== 0 ) { return; } if ( ev.button !== 0 ) { return; }
@ -278,6 +272,33 @@ dom.on('#showMatchedRules', 'click', ev => {
/******************************************************************************/ /******************************************************************************/
dom.on('[data-i18n-title="popupTipReport"]', 'click', ev => {
if ( ev.isTrusted !== true ) { return; }
let url;
try {
url = new URL(currentTab.url);
} catch(_) {
}
if ( url === undefined ) { return; }
const reportURL = new URL(runtime.getURL('/report.html'));
reportURL.searchParams.set('url', url.href);
reportURL.searchParams.set('mode', popupPanelData.level);
sendMessage({
what: 'gotoURL',
url: `${reportURL.pathname}${reportURL.search}`,
});
});
/******************************************************************************/
dom.on('[data-i18n-title="popupTipDashboard"]', 'click', ev => {
if ( ev.isTrusted !== true ) { return; }
if ( ev.button !== 0 ) { return; }
runtime.openOptionsPage();
});
/******************************************************************************/
async function init() { async function init() {
const [ tab ] = await browser.tabs.query({ const [ tab ] = await browser.tabs.query({
active: true, active: true,
@ -314,6 +335,10 @@ async function init() {
isNaN(currentTab.id) === false isNaN(currentTab.id) === false
); );
dom.cl.toggle('#reportFilterIssue', 'enabled',
/^https?:\/\//.test(url?.href)
);
const parent = qs$('#rulesetStats'); const parent = qs$('#rulesetStats');
for ( const details of popupPanelData.rulesetDetails || [] ) { for ( const details of popupPanelData.rulesetDetails || [] ) {
const div = dom.clone('#templates .rulesetDetails'); const div = dom.clone('#templates .rulesetDetails');

View File

@ -0,0 +1,155 @@
/*******************************************************************************
uBlock Origin - a comprehensive, efficient content blocker
Copyright (C) 2024-present Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see {http://www.gnu.org/licenses/}.
Home: https://github.com/gorhill/uBlock
*/
import { dnr, runtime } from './ext.js';
import { dom, qs$ } from './dom.js';
import { sendMessage } from './ext.js';
/******************************************************************************/
const reportedPage = (( ) => {
const url = new URL(window.location.href);
try {
const pageURL = url.searchParams.get('url');
if ( pageURL === null ) { return null; }
const parsedURL = new URL(pageURL);
parsedURL.username = '';
parsedURL.password = '';
parsedURL.hash = '';
const select = qs$('select[name="url"]');
dom.text(select.options[0], parsedURL.href);
if ( parsedURL.search !== '' ) {
const option = dom.create('option');
parsedURL.search = '';
dom.text(option, parsedURL.href);
select.append(option);
}
if ( parsedURL.pathname !== '/' ) {
const option = dom.create('option');
parsedURL.pathname = '';
dom.text(option, parsedURL.href);
select.append(option);
}
return {
hostname: parsedURL.hostname.replace(/^(m|mobile|www)\./, ''),
mode: url.searchParams.get('mode'),
};
} catch(ex) {
}
return null;
})();
/******************************************************************************/
function reportSpecificFilterType() {
return qs$('select[name="type"]').value;
}
/******************************************************************************/
function renderData(data, depth = 0) {
const indent = ' '.repeat(depth);
if ( Array.isArray(data) ) {
const out = [];
for ( const value of data ) {
out.push(renderData(value, depth));
}
return out.join('\n');
}
if ( typeof data !== 'object' || data === null ) {
return `${indent}${data}`;
}
const out = [];
for ( const [ name, value ] of Object.entries(data) ) {
if ( typeof value === 'object' && value !== null ) {
out.push(`${indent}${name}:`);
out.push(renderData(value, depth + 1));
continue;
}
out.push(`${indent}${name}: ${value}`);
}
return out.join('\n');
}
/******************************************************************************/
async function reportSpecificFilterIssue() {
const githubURL = new URL(
'https://github.com/uBlockOrigin/uAssets/issues/new?template=specific_report_from_ubol.yml'
);
const issueType = reportSpecificFilterType();
let title = `${reportedPage.hostname}: ${issueType}`;
if ( qs$('#isNSFW').checked ) {
title = `[nsfw] ${title}`;
}
githubURL.searchParams.set('title', title);
githubURL.searchParams.set(
'url_address_of_the_web_page',
'`' + qs$('select[name="url"]').value + '`'
);
githubURL.searchParams.set('category', issueType);
githubURL.searchParams.set('labels', 'uBOL');
const manifest = runtime.getManifest();
const rulesets = await dnr.getEnabledRulesets();
const defaultMode = await sendMessage({ what: 'getDefaultFilteringMode' });
const modes = [ 'no filtering', 'basic', 'optimal', 'complete' ];
const config = {
version: `uBOL ${manifest.version}`,
mode: `${modes[reportedPage.mode]} / ${modes[defaultMode]}`,
rulesets,
};
const configBody = [
'```yaml',
renderData(config),
'```',
'',
].join('\n');
githubURL.searchParams.set('configuration', configBody);
sendMessage({ what: 'gotoURL', url: githubURL.href });
}
/******************************************************************************/
(async ( ) => {
dom.on('[data-url]', 'click', ev => {
const elem = ev.target.closest('[data-url]');
const url = dom.attr(elem, 'data-url');
if ( typeof url !== 'string' || url === '' ) { return; }
sendMessage({ what: 'gotoURL', url });
ev.preventDefault();
});
if ( reportedPage !== null ) {
dom.on('[data-i18n="supportReportSpecificButton"]', 'click', ev => {
reportSpecificFilterIssue();
ev.preventDefault();
});
dom.on('[data-i18n="supportFindSpecificButton"]', 'click', ev => {
const url = new URL('https://github.com/uBlockOrigin/uAssets/issues');
url.searchParams.set('q', `is:issue sort:updated-desc "${reportedPage.hostname}" in:title`);
sendMessage({ what: 'gotoURL', url: url.href });
ev.preventDefault();
});
}
})();

View File

@ -7,7 +7,6 @@
<link rel="stylesheet" href="css/default.css"> <link rel="stylesheet" href="css/default.css">
<link rel="stylesheet" href="css/common.css"> <link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/fa-icons.css"> <link rel="stylesheet" href="css/fa-icons.css">
<link rel="stylesheet" href="css/dashboard-common.css">
<link rel="stylesheet" href="css/matched-rules.css"> <link rel="stylesheet" href="css/matched-rules.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"/>

View File

@ -13,6 +13,7 @@
</head> </head>
<body class="loading" data-section=""> <body class="loading" data-section="">
<div id="main"> <div id="main">
<div id="hostname"><span></span>&shy;<span></span></div> <div id="hostname"><span></span>&shy;<span></span></div>
<!-- -------- --> <!-- -------- -->
@ -30,6 +31,7 @@
<span></span> <span></span>
<span></span> <span></span>
<span id="showMatchedRules" class="fa-icon tool" tabindex="0" title="Show matched rules">list-alt<span class="caption">Show matched rules</span></span> <span id="showMatchedRules" class="fa-icon tool" tabindex="0" title="Show matched rules">list-alt<span class="caption">Show matched rules</span></span>
<span id="reportFilterIssue" class="fa-icon tool enabled" data-i18n-title="popupTipReport">comment-alt<span class="caption" data-i18n="popupTipReport"></span></span>
<span class="fa-icon tool enabled" tabindex="0" data-i18n-title="popupTipDashboard">cogs<span class="caption" data-i18n="popupTipDashboard"></span></span> <span class="fa-icon tool enabled" tabindex="0" data-i18n-title="popupTipDashboard">cogs<span class="caption" data-i18n="popupTipDashboard"></span></span>
</div> </div>
<!-- -------- --> <!-- -------- -->

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>uBO Lite — Report</title>
<link rel="stylesheet" href="css/default.css">
<link rel="stylesheet" href="css/common.css">
<link rel="stylesheet" href="css/dashboard-common.css">
<link rel="stylesheet" href="css/fa-icons.css">
<link rel="shortcut icon" type="image/png" href="img/icon_64.png">
</head>
<body>
<section>
<h3 data-i18n="supportS6H"></h3>
<p data-i18n="supportS3P1"></p>
<div class="supportEntry">
<hr>
<p data-i18n="supportS6P1S1"></p>
<button type="button" data-i18n="supportFindSpecificButton">_<span class="hover"></span></button>
</div>
<div class="supportEntry createEntry">
<hr>
<p>
<label data-i18n="supportS6URL"></label><br>
<select name="url">
<option></option>
</select>
</p>
<p>
<label data-i18n="supportS6Select1"></label><br>
<select name="type">
<option value="[unknown]" data-i18n="supportS6Select1Option0" selected disabled></option>
<option value="ads" data-i18n="supportS6Select1Option1"></option>
<option value="detection" data-i18n="supportS6Select1Option3"></option>
<option value="popups" data-i18n="supportS6Select1Option6"></option>
<option value="nuisance" data-i18n="supportS6Select1Option2"></option>
<option value="breakage" data-i18n="supportS6Select1Option5"></option>
<option value="privacy" data-i18n="supportS6Select1Option4"></option>
<option value="badware" data-i18n="supportS6Select1Option7"></option>
</select>
</p>
<p>
<label><span class="input checkbox"><input id="isNSFW" type="checkbox"><svg viewBox="0 0 24 24"><path d="M1.73,12.91 8.1,19.28 22.79,4.59"/></svg></span><span data-i18n="supportS6Checkbox1"></span></label>
</p>
<button type="button" data-i18n="supportReportSpecificButton" class="preferred">_<span class="hover"></span></button>
</div>
</section>
<script src="js/theme.js" type="module"></script>
<script src="js/fa-icons.js" type="module"></script>
<script src="js/i18n.js" type="module"></script>
<script src="js/report.js" type="module"></script>
</body>
</html>