diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/_locales/en/messages.json | 4 | ||||
-rw-r--r-- | src/about.html | 10 | ||||
-rw-r--r-- | src/css/common.css | 4 | ||||
-rw-r--r-- | src/css/popup.css | 45 | ||||
-rw-r--r-- | src/dashboard.html | 2 | ||||
-rw-r--r-- | src/js/about.js | 93 | ||||
-rw-r--r-- | src/js/background.js | 1 | ||||
-rw-r--r-- | src/js/dashboard.js | 2 | ||||
-rw-r--r-- | src/js/messaging.js | 17 | ||||
-rw-r--r-- | src/js/pagestore.js | 10 | ||||
-rw-r--r-- | src/js/popup.js | 24 | ||||
-rw-r--r-- | src/js/settings.js | 113 | ||||
-rw-r--r-- | src/js/storage.js | 5 | ||||
-rw-r--r-- | src/settings.html | 13 |
14 files changed, 167 insertions, 176 deletions
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 7039432..bdf6813 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -215,6 +215,10 @@ "message":"Make use of context menu where appropriate", "description":"English: Make use of context menu where appropriate" }, + "settingsAdvancedUserPrompt":{ + "message":"I am an advanced user (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Advanced-user-features'>About<\/a>)", + "description":"English: " + }, "settingsExperimentalPrompt":{ "message":"Enable experimental features (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Experimental-features'>About<\/a>)", "description":"English: Enable experimental features" diff --git a/src/about.html b/src/about.html index 9413ab9..77a8361 100644 --- a/src/about.html +++ b/src/about.html @@ -22,16 +22,6 @@ </ul> </ul> -<div style="margin:3em 0;border-top:1px solid #ccc;"></div> - -<div style="margin:1em 0 0 0;"> -<p><button type="button" id="export" data-i18n="aboutBackupDataButton"></button> - <button type="button" id="import" data-i18n="aboutRestoreDataButton"></button> - <input id="restoreFilePicker" type="file" accept="text/plain" class="hiddenFileInput"> -<p> -<p><button type="button" id="reset" data-i18n="aboutResetDataButton"></button> -</div> - <script src="js/vapi-common.js"></script> <script src="js/vapi-client.js"></script> <script src="js/udom.js"></script> diff --git a/src/css/common.css b/src/css/common.css index 0fd5e80..93fcd65 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -18,14 +18,14 @@ cursor: pointer; position: relative; } -[data-tip]:hover:after { +body:not(.advancedUser) [data-tip]:hover:after { background-color: #ffffee; border: 1px solid gray; border-radius: 3px; box-shadow: 1px 1px 3px gray; color: black; content: attr(data-tip); - font: 11px sans-serif; + font: 12px sans-serif; left: 0; line-height: 130%; min-width: 55%; diff --git a/src/css/popup.css b/src/css/popup.css index cb0ac5e..5d67f49 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -62,6 +62,7 @@ body[dir="rtl"] #panes > div:nth-of-type(2) { } #panes > div:nth-of-type(1) { + min-width: 150px; padding: 4px 5px 0 5px; } p { @@ -115,43 +116,17 @@ p { color: #444; } -#dfToggler::before { +body.advancedUser #dfToggler::before { color: gray; content: '+\202F'; cursor: pointer; font-size: 14px; line-height: 14px; } -#panes.dfEnabled #dfToggler::before { +body.advancedUser #panes.dfEnabled #dfToggler::before { content: '\2212\202F'; } -.dynamicFiltering div > .tip { - background-color: #fffff4; - border: 1px solid #888; - border-radius: 5px; - bottom: 20%; - box-shadow: 1px 1px 2px 0 rgba(0,0,0,0.8); - display: none; - font-size: small; - left: 8%; - padding: 0.25em; - position: fixed; - right: 8%; - text-align: center; - } -.dynamicFiltering div:not(.blocked):hover > .tip:nth-of-type(1) { - display: block; - } -.dynamicFiltering div.blocked:hover > .tip:nth-of-type(2) { - display: block; - } -.dynamicFiltering div > .tip code { - background-color: #f8f8f8; - font: normal monospace; - padding: 1px 0; - } - #dynamicFilteringContainer { border: 0; font-size: 12px; @@ -269,17 +244,3 @@ p { #dynamicFilteringContainer span.bRule #actionSelector > span:nth-of-type(3) { visibility: hidden; } -#hotspotTip { - background-color: #ffe; - border: 1px dotted #ddb; - border-radius: 5px; - height: 50vh; - opacity: 1; - padding: 4px; - position: fixed; - right: 10px; - text-align: center; - top: 25vh; - width: 20vw; - z-index: 100; - }
\ No newline at end of file diff --git a/src/dashboard.html b/src/dashboard.html index 4c36f62..ac7e5a6 100644 --- a/src/dashboard.html +++ b/src/dashboard.html @@ -11,11 +11,11 @@ <div id="dashboard-nav"> <div id="dashboard-nav-widgets"> <span data-i18n="extName"></span> + <a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a> <a class="tabButton" href="#3p-filters.html" data-i18n="3pPageName"></a> <a class="tabButton" href="#1p-filters.html" data-i18n="1pPageName"></a> <a class="tabButton" href="#dyna-rules.html" data-i18n="rulesPageName"></a> <a class="tabButton" href="#whitelist.html" data-i18n="whitelistPageName"></a> - <a class="tabButton" href="#settings.html" data-i18n="settingsPageName"></a> <a class="tabButton" href="#about.html" data-i18n="aboutPageName"></a> </div> </div> diff --git a/src/js/about.js b/src/js/about.js index 2e2c5c7..66155c6 100644 --- a/src/js/about.js +++ b/src/js/about.js @@ -33,101 +33,8 @@ var messager = vAPI.messaging.channel('about.js'); /******************************************************************************/ -var exportToFile = function() { - var onUserDataReady = function(userData) { - if (!userData) { - return; - } - var now = new Date(); - var filename = vAPI.i18n('aboutBackupFilename') - .replace('{{datetime}}', now.toLocaleString()) - .replace(/ +/g, '_'); - vAPI.download({ - 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')), - 'filename': filename - }); - }; - - messager.send({ what: 'getUserData' }, onUserDataReady); -}; - -/******************************************************************************/ - -var handleImportFilePicker = function() { - var fileReaderOnLoadHandler = function() { - var userData; - try { - userData = JSON.parse(this.result); - if ( typeof userData !== 'object' ) { - throw 'Invalid'; - } - if ( typeof userData.userSettings !== 'object' ) { - throw 'Invalid'; - } - if ( typeof userData.netWhitelist !== 'string' ) { - throw 'Invalid'; - } - if ( typeof userData.filterLists !== 'object' ) { - throw 'Invalid'; - } - } - catch (e) { - userData = undefined; - } - if ( userData === undefined ) { - window.alert(vAPI.i18n('aboutRestoreDataError')); - return; - } - var time = new Date(userData.timeStamp); - var msg = vAPI.i18n('aboutRestoreDataConfirm') - .replace('{{time}}', time.toLocaleString()); - var proceed = window.confirm(msg); - if ( proceed ) { - messager.send({ what: 'restoreUserData', userData: userData }); - } - }; - - var file = this.files[0]; - if ( file === undefined || file.name === '' ) { - return; - } - if ( file.type.indexOf('text') !== 0 ) { - return; - } - var fr = new FileReader(); - fr.onload = fileReaderOnLoadHandler; - fr.readAsText(file); -}; - -/******************************************************************************/ - -var startImportFilePicker = function() { - var input = document.getElementById('restoreFilePicker'); - // Reset to empty string, this will ensure an change event is properly - // triggered if the user pick a file, even if it is the same as the last - // one picked. - input.value = ''; - input.click(); -}; - -/******************************************************************************/ - -var resetUserData = function() { - var msg = vAPI.i18n('aboutResetDataConfirm'); - var proceed = window.confirm(msg); - if ( proceed ) { - messager.send({ what: 'resetUserData' }); - } -}; - -/******************************************************************************/ - var onAppDataReady = function(appData) { uDom('#aboutNameVer').html(appData.name + ' v' + appData.version); - uDom('#export').on('click', exportToFile); - uDom('#import').on('click', startImportFilePicker); - uDom('#reset').on('click', resetUserData); - uDom('#restoreFilePicker').on('change', handleImportFilePicker); }; messager.send({ what: 'getAppData' }, onAppDataReady); diff --git a/src/js/background.js b/src/js/background.js index 4a98ab1..4306d65 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -52,6 +52,7 @@ var defaultExternalLists = [ return { userSettings: { + advancedUserEnabled: false, autoUpdate: true, collapseBlocked: true, contextMenuEnabled: true, diff --git a/src/js/dashboard.js b/src/js/dashboard.js index 6779f27..ba916e2 100644 --- a/src/js/dashboard.js +++ b/src/js/dashboard.js @@ -59,7 +59,7 @@ uDom.onLoad(function() { } } if ( !tab ) { - tab = '3p-filters'; + tab = 'settings'; } loadDashboardPanel(tab + '.html', q); uDom('.tabButton').on('click', onTabClickHandler); diff --git a/src/js/messaging.js b/src/js/messaging.js index aa95a7e..90ec132 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -171,17 +171,18 @@ var getDynamicFilterRules = function(srcHostname, desHostnames) { var getStats = function(tabId) { var r = { + advancedUserEnabled: µb.userSettings.advancedUserEnabled, appName: vAPI.app.name, appVersion: vAPI.app.version, - globalBlockedRequestCount: µb.localSettings.blockedRequestCount, + cosmeticFilteringSwitch: false, + dfEnabled: µb.userSettings.dynamicFilteringEnabled, globalAllowedRequestCount: µb.localSettings.allowedRequestCount, - tabId: tabId, + globalBlockedRequestCount: µb.localSettings.blockedRequestCount, + netFilteringSwitch: false, pageURL: '', - pageBlockedRequestCount: 0, pageAllowedRequestCount: 0, - netFilteringSwitch: false, - cosmeticFilteringSwitch: false, - dfEnabled: µb.userSettings.dynamicFilteringEnabled + pageBlockedRequestCount: 0, + tabId: tabId }; var pageStore = µb.pageStoreFromTabId(tabId); if ( pageStore ) { @@ -811,7 +812,7 @@ vAPI.messaging.listen('stats.js', onMessage); /******************************************************************************/ /******************************************************************************/ -// about.js +// settings.js (function() { @@ -902,7 +903,7 @@ var onMessage = function(request, sender, callback) { callback(response); }; -vAPI.messaging.listen('about.js', onMessage); +vAPI.messaging.listen('settings.js', onMessage); /******************************************************************************/ diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 24cb3ec..f5f52bf 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -615,10 +615,12 @@ PageStore.prototype.filterRequest = function(context) { // - Evaluating dynamic filtering is much faster than static filtering // We evaluate dynamic filtering first, and hopefully we can skip // evaluation of static filtering. - var df = µb.dynamicNetFilteringEngine.clearRegisters(); - df.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType); - if ( df.mustBlockOrAllow() ) { - result = df.toFilterString(); + if ( µb.userSettings.advancedUserEnabled ) { + var df = µb.dynamicNetFilteringEngine.clearRegisters(); + df.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType); + if ( df.mustBlockOrAllow() ) { + result = df.toFilterString(); + } } // Static filtering never override dynamic filtering diff --git a/src/js/popup.js b/src/js/popup.js index 0d706bb..48775f4 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -117,7 +117,7 @@ var reRulekeyCompareNoise = /[^a-z0-9.]/g; var addDynamicFilterRow = function(des) { var row = uDom('#templates > div:nth-of-type(1)').clone(); row.descendants('[data-des]').attr('data-des', des); - row.descendants('div > span:nth-of-type(1)').text(des); + row.descendants('span:nth-of-type(1)').text(des); var hnDetails = popupData.hostnameDict[des] || {}; var isDomain = des === hnDetails.domain; @@ -245,16 +245,17 @@ var renderPopup = function() { var isHTTP = /^https?:\/\/[0-9a-z]/.test(popupData.pageURL); + // Condition for dynamic filtering toggler: + // - Advanced user + uDom('body').toggleClass('advancedUser', popupData.advancedUserEnabled); + // Conditions for request log: - // - `http` or `https` scheme + // - `http` or `https` scheme uDom('#gotoLog').toggleClass('enabled', isHTTP); // Conditions for element picker: - // - `http` or `https` scheme - uDom('#gotoPick').toggleClass( - 'enabled', - isHTTP - ); + // - `http` or `https` scheme + uDom('#gotoPick').toggleClass('enabled', isHTTP); var or = vAPI.i18n('popupOr'); var blocked = popupData.pageBlockedRequestCount; @@ -289,15 +290,15 @@ var renderPopup = function() { '%</span>' ); } + uDom('#total-blocked').html(html.join('')); // Build dynamic filtering pane only if in use - if ( popupData.dfEnabled ) { + if ( popupData.dfEnabled && popupData.advancedUserEnabled ) { syncAllDynamicFilters(); } - uDom('#total-blocked').html(html.join('')); uDom('#switch .fa').toggleClass('off', popupData.pageURL === '' || !popupData.netFilteringSwitch); - uDom('#panes').toggleClass('dfEnabled', popupData.dfEnabled); + uDom('#panes').toggleClass('dfEnabled', popupData.dfEnabled && popupData.advancedUserEnabled); }; /******************************************************************************/ @@ -373,6 +374,9 @@ var gotoLink = function(ev) { /******************************************************************************/ var toggleDynamicFiltering = function(ev) { + if ( uDom('body').hasClass('advancedUser') === false ) { + return; + } var el = uDom('#panes'); popupData.dfEnabled = !popupData.dfEnabled; messager.send({ diff --git a/src/js/settings.js b/src/js/settings.js index acd1625..cf9981b 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -20,11 +20,12 @@ */ /* global vAPI, uDom */ -'use strict'; /******************************************************************************/ -uDom.onLoad(function() { +(function() { + +'use strict'; /******************************************************************************/ @@ -32,6 +33,95 @@ var messager = vAPI.messaging.channel('settings.js'); /******************************************************************************/ +var exportToFile = function() { + var onUserDataReady = function(userData) { + if (!userData) { + return; + } + var now = new Date(); + var filename = vAPI.i18n('aboutBackupFilename') + .replace('{{datetime}}', now.toLocaleString()) + .replace(/ +/g, '_'); + vAPI.download({ + 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')), + 'filename': filename + }); + }; + + messager.send({ what: 'getUserData' }, onUserDataReady); +}; + +/******************************************************************************/ + +var handleImportFilePicker = function() { + var fileReaderOnLoadHandler = function() { + var userData; + try { + userData = JSON.parse(this.result); + if ( typeof userData !== 'object' ) { + throw 'Invalid'; + } + if ( typeof userData.userSettings !== 'object' ) { + throw 'Invalid'; + } + if ( typeof userData.netWhitelist !== 'string' ) { + throw 'Invalid'; + } + if ( typeof userData.filterLists !== 'object' ) { + throw 'Invalid'; + } + } + catch (e) { + userData = undefined; + } + if ( userData === undefined ) { + window.alert(vAPI.i18n('aboutRestoreDataError')); + return; + } + var time = new Date(userData.timeStamp); + var msg = vAPI.i18n('aboutRestoreDataConfirm') + .replace('{{time}}', time.toLocaleString()); + var proceed = window.confirm(msg); + if ( proceed ) { + messager.send({ what: 'restoreUserData', userData: userData }); + } + }; + + var file = this.files[0]; + if ( file === undefined || file.name === '' ) { + return; + } + if ( file.type.indexOf('text') !== 0 ) { + return; + } + var fr = new FileReader(); + fr.onload = fileReaderOnLoadHandler; + fr.readAsText(file); +}; + +/******************************************************************************/ + +var startImportFilePicker = function() { + var input = document.getElementById('restoreFilePicker'); + // Reset to empty string, this will ensure an change event is properly + // triggered if the user pick a file, even if it is the same as the last + // one picked. + input.value = ''; + input.click(); +}; + +/******************************************************************************/ + +var resetUserData = function() { + var msg = vAPI.i18n('aboutResetDataConfirm'); + var proceed = window.confirm(msg); + if ( proceed ) { + messager.send({ what: 'resetUserData' }); + } +}; + +/******************************************************************************/ + var changeUserSettings = function(name, value) { messager.send({ what: 'userSettings', @@ -63,15 +153,30 @@ var onUserSettingsReceived = function(details) { changeUserSettings('contextMenuEnabled', this.checked); }); + uDom('#advanced-user-enabled') + .prop('checked', details.advancedUserEnabled === true) + .on('change', function(){ + changeUserSettings('advancedUserEnabled', this.checked); + }); + uDom('#experimental-enabled') .prop('checked', details.experimentalEnabled === true) .on('change', function(){ changeUserSettings('experimentalEnabled', this.checked); }); -}; -messager.send({ what: 'userSettings' }, onUserSettingsReceived); + uDom('#export').on('click', exportToFile); + uDom('#import').on('click', startImportFilePicker); + uDom('#reset').on('click', resetUserData); + uDom('#restoreFilePicker').on('change', handleImportFilePicker); +}; /******************************************************************************/ +uDom.onLoad(function() { + messager.send({ what: 'userSettings' }, onUserSettingsReceived); }); + +/******************************************************************************/ + +})(); diff --git a/src/js/storage.js b/src/js/storage.js index 044ec86..b98a67c 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -670,11 +670,14 @@ µb.dynamicNetFilteringEngine.fromObsoleteSelfie(settings.dynamicFilteringSelfie); µb.userSettings.dynamicFilteringString = µb.dynamicNetFilteringEngine.toString(); µb.XAL.keyvalSetOne('dynamicFilteringString', µb.userSettings.dynamicFilteringString); + + // Auto-enable advanced user if there were dynamic rules + µb.userSettings.advancedUserEnabled = true; + µb.XAL.keyvalSetOne('advancedUserEnabled', true); } delete µb.userSettings.dynamicFilteringSelfie; µb.XAL.keyvalRemoveOne('dynamicFilteringSelfie'); } - µb.dynamicNetFilteringEngine.fromString(µb.userSettings.dynamicFilteringString); }; this.loadUserSettings(onUserSettingsReady); diff --git a/src/settings.html b/src/settings.html index 242370e..fa5fb1e 100644 --- a/src/settings.html +++ b/src/settings.html @@ -8,6 +8,7 @@ <style> ul { list-style-type: none; + padding-left: 1em; } #experimental-enabled { margin-top: 1em; @@ -21,9 +22,21 @@ ul { <li><input id="collapse-blocked" type="checkbox"><label data-i18n="settingsCollapseBlockedPrompt" for="collapse-blocked"></label> <li><input id="icon-badge" type="checkbox"><label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label> <li><input id="context-menu-enabled" type="checkbox"><label data-i18n="settingsContextMenuPrompt" for="context-menu-enabled"></label> + <li><input id="advanced-user-enabled" type="checkbox"><label data-i18n="settingsAdvancedUserPrompt" for="advanced-user-enabled"></label> + <li><input id="experimental-enabled" type="checkbox"><label data-i18n="settingsExperimentalPrompt" for="experimental-enabled"></label> </ul> +<div style="margin:3em 0;border-top:1px solid #ccc;"></div> + +<div style="margin:1em 0 0 1em;"> + <p><button type="button" id="export" data-i18n="aboutBackupDataButton"></button>  + <button type="button" id="import" data-i18n="aboutRestoreDataButton"></button> + <input id="restoreFilePicker" type="file" accept="text/plain" class="hiddenFileInput"> + <p> + <p><button type="button" id="reset" data-i18n="aboutResetDataButton"></button> +</div> + <script src="js/vapi-common.js"></script> <script src="js/vapi-client.js"></script> <script src="js/udom.js"></script> |