From a45a21f337216d7d4aaddb5a454ed4842eca3806 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 6 Apr 2020 14:00:19 -0400 Subject: [PATCH] Second pass to re-design the dashboard Related commit: - https://github.com/gorhill/uBlock/commit/453f5450b6e6550618bf97b5b0541f5f46c35d8e The changes in this commit are mostly related to the "Filter lists" pane. An eye icon has been added, which purpose is to view the content of a list. Clicking on the name of the list will toggle the list's checkbox. --- src/3p-filters.html | 77 +++++++++-------- src/_locales/en/messages.json | 4 + src/css/3p-filters.css | 150 ++++++++++++++++++---------------- src/css/common.css | 1 - src/css/dashboard-common.css | 2 +- src/css/dashboard.css | 6 +- src/css/dyna-rules.css | 3 - src/css/settings.css | 6 +- src/css/whitelist.css | 6 -- src/js/3p-filters.js | 28 +++++-- src/js/whitelist.js | 4 +- 11 files changed, 154 insertions(+), 133 deletions(-) diff --git a/src/3p-filters.html b/src/3p-filters.html index cda8e41b0..445880025 100644 --- a/src/3p-filters.html +++ b/src/3p-filters.html @@ -15,46 +15,53 @@
- - +
+ + + +
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 808e8b361..509f35bfa 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -459,6 +459,10 @@ "message":"Out of date.", "description":"used as a tooltip for the out-of-date icon beside a list" }, + "3pViewContent":{ + "message":"view content", + "description":"used as a tooltip for eye icon beside a list" + }, "3pLastUpdate":{ "message":"Last update: {{ago}}.\nClick to force an update.", "description":"used as a tooltip for the clock icon beside a list" diff --git a/src/css/3p-filters.css b/src/css/3p-filters.css index 3f4efa06f..8fc41ce84 100644 --- a/src/css/3p-filters.css +++ b/src/css/3p-filters.css @@ -1,32 +1,34 @@ @keyframes spin { - 0% { transform: rotate(0deg); -webkit-transform: rotate(0deg); } - 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg); } + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } } -ul { - list-style-type: none; - padding-left: 1em; - padding-right: 0; - } -body[dir="rtl"] ul { - padding-left: 0; - padding-right: 1em; - } -ul.root { +body { + border: 0; + font: 14px/21px sans-serif; + margin: 0; padding: 0; } +.root { + background-color: white; + overflow: auto; + padding: 0.5em 0; + } +.entry { + align-items: center; + display: flex; + margin: 0.5em 0; + } +#actions { + position: sticky; + top: 0; + z-index: 10; + } #options li { margin-bottom: 0.5em; } #listsOfBlockedHostsPrompt { cursor: pointer; } -#listsOfBlockedHostsPrompt:before { - color: #888; - content: '\2212 '; - } -body.hideUnused #listsOfBlockedHostsPrompt:before { - content: '+ '; - } #lists { margin: 0.5em 0 0 0; padding: 0; @@ -36,16 +38,25 @@ body.hideUnused #listsOfBlockedHostsPrompt:before { padding: 0; list-style-type: none; } +#listsOfBlockedHostsPrompt::before, +.groupEntry:not([data-groupkey="user"]) .geDetails::before { + color: #888; + content: '\2212'; + font-family: monospace; + font-size: large; + margin-inline-end: 0.25em; + -webkit-margin-end: 0.25em; + } +body.hideUnused #listsOfBlockedHostsPrompt::before, +.groupEntry.hideUnused:not([data-groupkey="user"]) .geDetails::before { + content: '+'; + } +.groupEntry { + margin: 0.5em 0; + } .groupEntry .geDetails { cursor: pointer; } -.groupEntry:not([data-groupkey="user"]) .geDetails:before { - color: #888; - content: '\2212 '; - } -.groupEntry.hideUnused:not([data-groupkey="user"]) .geDetails:before { - content: '+ '; - } .groupEntry .geName { pointer-events: none; } @@ -57,9 +68,12 @@ body.hideUnused #listsOfBlockedHostsPrompt:before { margin: 0.25em 0 0 0; padding-left: 1em; } +.listEntries { + margin-inline-start: 0.7em; + -webkit-margin-start: 0.7em; + } .listEntry { - margin: 0 auto 0 auto; - padding: 0.2em 0; + margin: 0.5em 0; white-space: nowrap; } .groupEntry:not([data-groupkey="user"]) .listEntry.unused { @@ -69,115 +83,113 @@ body.hideUnused #listsOfBlockedHostsPrompt:before { margin-right: 0.5em; unicode-bidi: embed; } -.listEntry.toRemove > input[type="checkbox"] { +.listEntry input[type="checkbox"] { + margin-right: 0.5em; + } +.listEntry.toRemove input[type="checkbox"] { visibility: hidden; } -.listEntry.toRemove > a.content { +.listEntry.toRemove .listname { text-decoration: line-through; } -.listEntry > .fa { +.listEntry .fa { color: inherit; display: none; font-size: 110%; opacity: 0.5; vertical-align: baseline; } -.listEntry > a.towiki { +.listEntry .content { display: inline-block; } -.listEntry > a.fa:hover { +.listEntry a.towiki { + display: inline-block; + } +.listEntry a.fa:hover { opacity: 1; } .listEntry.support > a.support { display: inline-block; } -.listEntry > a.remove, -.listEntry > a.remove:visited { +.listEntry .remove { color: darkred; + cursor: pointer; } -.listEntry.external > a.remove { +.listEntry.external .remove { display: inline-block; } -.listEntry.mustread > a.mustread { +.listEntry.mustread a.mustread { display: inline-block; } -.listEntry.mustread > a.mustread:hover { +.listEntry.mustread a.mustread:hover { color: mediumblue; } -.listEntry > .counts { +.listEntry .counts { display: none; font-size: smaller; } -.listEntry > input[type="checkbox"]:checked ~ .counts { +.listEntry.checked .counts { display: inline; } .dim { opacity: 0.6; } -#buttonApply { - display: initial; - position: fixed; - right: 1em; - z-index: 10; - } -body[dir=rtl] #buttonApply { - right: auto; - left: 1em; - } -#buttonApply.disabled { - display: none; - } -.listEntry span.status { +.listEntry .status { color: #444; cursor: default; display: none; } -.listEntry span.status:hover { +.listEntry .status:hover { opacity: 1; } -.listEntry span.unsecure { +.listEntry .unsecure { color: darkred; } -.listEntry.unsecure > input[type="checkbox"]:checked ~ span.unsecure { +.listEntry.checked.unsecure .unsecure { display: inline-block; } -.listEntry span.failed { +.listEntry .failed { color: darkred; } -.listEntry.failed span.failed { +.listEntry.failed .failed { display: inline-block; } -.listEntry span.cache { +.listEntry .cache { cursor: pointer; } -.listEntry.cached:not(.obsolete) > input[type="checkbox"]:checked ~ span.cache { +.listEntry.checked.cached:not(.obsolete) .cache { display: inline-block; } -.listEntry span.obsolete { +.listEntry .obsolete { color: hsl(36, 100%, 40%); } -body:not(.updating) .listEntry.obsolete > input[type="checkbox"]:checked ~ span.obsolete { +body:not(.updating) .listEntry.checked.obsolete .obsolete { display: inline-block; } -.listEntry span.updating { +.listEntry .updating { transform-origin: 50% 46%; } -body.updating .listEntry.obsolete > input[type="checkbox"]:checked ~ span.updating { +body.updating .listEntry.checked.obsolete .updating { animation: spin 2s linear infinite; display: inline-block; } -.listEntry.toImport > input[type="checkbox"] ~ textarea { +.listEntry.toImport input[type="checkbox"] ~ textarea { border: 1px solid #ccc; box-sizing: border-box; display: block; font-size: smaller; height: 6em; - margin-left: 2em; resize: vertical; visibility: hidden; white-space: pre; - width: calc(100% - 4em); + width: 100%; } -.listEntry.toImport > input[type="checkbox"]:checked ~ textarea { +.listEntry.toImport input[type="checkbox"]:checked ~ textarea { visibility: visible; } + +@media (pointer: coarse) { + #dashboard-nav { + font: 16px/24px sans-serif; + } +} diff --git a/src/css/common.css b/src/css/common.css index c6499ef5a..976598b4a 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -72,7 +72,6 @@ body[dir="rtl"] button.custom.iconifiable > .fa { @media (max-width: 640px) { button.custom.iconifiable > .fa { - font-size: 150%; padding: 0; } button.custom.iconifiable > [data-i18n] { diff --git a/src/css/dashboard-common.css b/src/css/dashboard-common.css index 990524798..32407824a 100644 --- a/src/css/dashboard-common.css +++ b/src/css/dashboard-common.css @@ -1,7 +1,7 @@ body { background-color: #fff; box-sizing: border-box; - color: #000; + color: #20123a; margin: 0; padding: 0; } diff --git a/src/css/dashboard.css b/src/css/dashboard.css index 1c5e4da80..db187a9ae 100644 --- a/src/css/dashboard.css +++ b/src/css/dashboard.css @@ -33,16 +33,16 @@ html, body { .tabButton { border: 0; border-bottom: 3px solid #f9f9fb; - color: #20123a; cursor: pointer; - padding: 0.5em 1.5em; + padding: 0.5em 1.4em 0.3em 1.4em; text-decoration: none; white-space: nowrap; } .tabButton:focus { outline: 0; } -.tabButton:active,.tabButton:visited { +.tabButton:active, +.tabButton:visited { color: #20123a; } .tabButton.selected { diff --git a/src/css/dyna-rules.css b/src/css/dyna-rules.css index 5d4342414..7cdd5ccc5 100644 --- a/src/css/dyna-rules.css +++ b/src/css/dyna-rules.css @@ -18,9 +18,6 @@ body { #diff .tools > * { margin-bottom: 0.5em; } -#diff .tools .fa { - font-size: large; - } #diff .ruleActions { border: 0; box-sizing: border-box; diff --git a/src/css/settings.css b/src/css/settings.css index 8bb69d907..58f173617 100644 --- a/src/css/settings.css +++ b/src/css/settings.css @@ -10,22 +10,20 @@ hr { margin: 1.5em 0; } .body { - color: #20123a; margin-top: 1em; } .entries { margin: 0.5em 0; } .section { - font-size: large; font-weight: bold; margin-top: 0.75em; } .synopsis { - font-size: smaller; + font-size: 90%; } .entry { - align-items: baseline; + align-items: center; display: flex; margin: 0.5em 0; } diff --git a/src/css/whitelist.css b/src/css/whitelist.css index a5ca328f2..fe116381b 100644 --- a/src/css/whitelist.css +++ b/src/css/whitelist.css @@ -10,9 +10,3 @@ body { text-align: left; width: 100%; } -.codeMirrorContainer .cm-builtin { - color: #00F; - } -.codeMirrorContainer .cm-comment.cm-builtin { - color: #88F; - } diff --git a/src/js/3p-filters.js b/src/js/3p-filters.js index ae23ed2d7..9e6379f0f 100644 --- a/src/js/3p-filters.js +++ b/src/js/3p-filters.js @@ -86,15 +86,17 @@ const renderFilterLists = function(soft) { li = listEntryTemplate.clone().nodeAt(0); } const on = entry.off !== true; + li.classList.toggle('checked', on); let elem; if ( li.getAttribute('data-listkey') !== listKey ) { li.setAttribute('data-listkey', listKey); elem = li.querySelector('input[type="checkbox"]'); elem.checked = on; - elem = li.querySelector('a:nth-of-type(1)'); + elem = li.querySelector('.listname'); + elem.textContent = listNameFromListKey(listKey); + elem = li.querySelector('a.content'); elem.setAttribute('href', 'asset-viewer.html?url=' + encodeURI(listKey)); elem.setAttribute('type', 'text/html'); - elem.textContent = listNameFromListKey(listKey); li.classList.remove('toRemove'); if ( entry.supportName ) { li.classList.add('support'); @@ -321,7 +323,7 @@ const renderWidgets = function() { ); uDom('#buttonUpdate').toggleClass( 'disabled', - document.querySelector('body:not(.updating) #lists .listEntry.obsolete:not(.toRemove) > input[type="checkbox"]:checked') === null + document.querySelector('body:not(.updating) #lists .listEntry.obsolete:not(.toRemove) input[type="checkbox"]:checked') === null ); }; @@ -377,20 +379,28 @@ const hashFromCurrentFromSettings = function() { /******************************************************************************/ +const onListsetChanged = function(ev) { + const input = ev.target; + const li = input.closest('.listEntry'); + li.classList.toggle('checked', input.checked); + onFilteringSettingsChanged(); +}; + +/******************************************************************************/ + const onFilteringSettingsChanged = function() { renderWidgets(); }; /******************************************************************************/ -const onRemoveExternalList = function(ev) { +const onRemoveExternalList = function() { const liEntry = uDom(this).ancestors('[data-listkey]'); const listKey = liEntry.attr('data-listkey'); if ( listKey ) { liEntry.toggleClass('toRemove'); renderWidgets(); } - ev.preventDefault(); }; /******************************************************************************/ @@ -539,7 +549,7 @@ const toggleHideUnusedLists = function(which) { groupSelector = '.groupEntry[data-groupkey="' + which + '"] '; uDom(groupSelector).toggleClass('hideUnused', mustHide); } - uDom(groupSelector + '.listEntry > input[type="checkbox"]:not(:checked)') + uDom(groupSelector + '.listEntry input[type="checkbox"]:not(:checked)') .ancestors('.listEntry[data-listkey]') .toggleClass('unused', mustHide); vAPI.localStorage.setItem( @@ -549,7 +559,7 @@ const toggleHideUnusedLists = function(which) { }; const revealHiddenUsedLists = function() { - uDom('#lists .listEntry.unused > input[type="checkbox"]:checked') + uDom('#lists .listEntry.unused input[type="checkbox"]:checked') .ancestors('.listEntry[data-listkey]') .removeClass('unused'); }; @@ -659,8 +669,8 @@ uDom('#buttonUpdate').on('click', ( ) => { buttonUpdateHandler(); }); uDom('#buttonPurgeAll').on('click', ev => { buttonPurgeAllHandler(ev.ctrlKey && ev.shiftKey); }); -uDom('#lists').on('change', '.listEntry > input', onFilteringSettingsChanged); -uDom('#lists').on('click', '.listEntry > a.remove', onRemoveExternalList); +uDom('#lists').on('change', '.listEntry input', onListsetChanged); +uDom('#lists').on('click', '.listEntry .remove', onRemoveExternalList); uDom('#lists').on('click', 'span.cache', onPurgeClicked); uDom('#externalLists').on('input', onFilteringSettingsChanged); diff --git a/src/js/whitelist.js b/src/js/whitelist.js index 63e77ab11..546308df2 100644 --- a/src/js/whitelist.js +++ b/src/js/whitelist.js @@ -52,13 +52,13 @@ CodeMirror.defineMode("ubo-whitelist-directives", function() { } if ( reComment.test(line) ) { return whitelistDefaultSet.has(directiveFromLine(line)) - ? 'builtin comment' + ? 'keyword comment' : 'comment'; } if ( line.indexOf('/') === -1 ) { if ( reBadHostname.test(line) ) { return 'error'; } if ( whitelistDefaultSet.has(line.trim()) ) { - return 'builtin'; + return 'keyword'; } return null; }