diff --git a/manage/manage.css b/manage/manage.css index ba751b93..ee8c664f 100644 --- a/manage/manage.css +++ b/manage/manage.css @@ -232,6 +232,7 @@ a:hover { display: none; } +.oldUI .disabled h2::after, .entry.usercss .style-name-link::after { font-size: 11px; border-radius: 4px; @@ -240,14 +241,32 @@ a:hover { content: "UC"; background-color: hsla(180, 35%, 50%, .35); padding: 2px 3px; + color: #000; +} +.oldUI .disabled h2::after { + content: var(--genericDisabledLabel); + text-transform: lowercase; + font-weight: normal; + background: rgba(128, 128, 128, .2); + padding: 2px 5px 3px; + vertical-align: middle; +} +.oldUI .entry.usercss .style-name-link::after { + content: "usercss"; + font-weight: normal; + vertical-align: middle; } .disabled h2 .style-name-link, -.disabled .actions, -.disabled .applies-to { - opacity: 0.6; +.disabled .applies-to, +.newUI .disabled.entry .svg-icon { + color: #888; + fill: #c4c4c4; font-weight: normal; - transition: opacity .5s .1s; + transition: color .5s .1s, fill .5s .1s; +} +.disabled.usercss .style-name-link::after { + background-color: hsla(180, 35%, 50%, .2); } .disabled:hover .actions { @@ -321,10 +340,6 @@ a:hover { margin-bottom: .75rem; } -.newUI .disabled { - opacity: 1; -} - .newUI .entry { display: table-row; padding-top: 0; diff --git a/manage/manage.js b/manage/manage.js index 1cada1fd..eeb334fe 100644 --- a/manage/manage.js +++ b/manage/manage.js @@ -54,7 +54,11 @@ Object.assign(newUI, { id === 'sliders' ? `ui.${id}` : id === 'enabled' ? 'manage.newUI' : `manage.newUI.${id}`, - renderClass: () => document.documentElement.classList.toggle('newUI', newUI.enabled), + renderClass: () => { + const cl = document.documentElement.classList; + cl.toggle('newUI', newUI.enabled); + cl.toggle('oldUI', !newUI.enabled); + }, tpl: { getToggle() { return t.template[newUI.sliders ? 'toggleSlider' : 'toggleChecker'].cloneNode(true); @@ -112,6 +116,7 @@ const handleEvent = {}; // translate CSS manually document.styleSheets[0].insertRule( `:root {${[ + 'genericDisabledLabel', 'updateAllCheckSucceededSomeEdited', 'filteredStylesAllHidden', ].map(id => `--${id}:"${CSS.escape(t(id))}";`).join('') diff --git a/options/onoffswitch.css b/options/onoffswitch.css index 1af404d6..6d262ac5 100644 --- a/options/onoffswitch.css +++ b/options/onoffswitch.css @@ -80,6 +80,7 @@ bottom: 0; margin: 0; padding: 0 4px 0 18px; + pointer-events: none; } .entry .onoffswitch span { position: absolute; @@ -109,8 +110,8 @@ pointer-events: all; } .entry .onoffswitch input + span::before { - width: 9px; - height: 9px; + width: 7px; + height: 7px; left: 2px; right: auto; margin: auto; diff --git a/popup/popup.css b/popup/popup.css index a6024738..c102188b 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -27,8 +27,8 @@ body { } body > div:not(#installed):not(#message-box):not(.colorpicker-popup) { - margin-left: var(--outer-padding); - margin-right: var(--outer-padding); + padding-left: var(--outer-padding); + padding-right: var(--outer-padding); } .firefox .chromium-only { @@ -141,8 +141,6 @@ body.blocked > DIV { #installed { border-bottom: 1px solid black; - padding-bottom: 2px; - padding-top: 2px; max-height: 445px; overflow-y: auto; counter-reset: style-number; @@ -222,8 +220,17 @@ html[style] .entry-content { opacity: 1; } -.entry.disabled .style-name { +.entry.disabled .style-name, +.entry.disabled .svg-icon { font-weight: normal; + color: #888; + fill: #aaa; +} +.entry.disabled:hover .svg-icon { + fill: #666; +} +.entry.disabled:hover a:hover .svg-icon { + fill: #000; } .entry .main-controls { @@ -238,6 +245,12 @@ html[style] .entry-content { .entry .onoffswitch { padding: 0 0 0 6px; } +.entry .onoffswitch input { + pointer-events: none; +} +.style-name:hover .onoffswitch span { + box-shadow: inset 1px 1px 3px rgba(0, 0, 0, .8); +} .entry:nth-child(even) { background-color: rgba(0, 0, 0, 0.05); @@ -305,7 +318,9 @@ a.configure[target="_blank"] .svg-icon.config { opacity: .2; transition: opacity .5s ease-in-out .25s, color .5s ease-in-out .25s; } - +.not-applied .style-name { + opacity: .5; +} .not-applied:hover .checker, .not-applied:hover .style-name, .not-applied:hover .actions > * { @@ -499,7 +514,7 @@ body > .actions { vertical-align: middle; } -body.blocked #installed > *, +body.blocked #installed > :not(.frame), body.blocked .actions > .main-controls { display: none; } @@ -773,7 +788,7 @@ body.blocked .actions > .main-controls { margin: 0 .25em .25em 0; } -.unreachable .entry { +.unreachable .entry:not(.frame) { opacity: .25; } diff --git a/popup/popup.js b/popup/popup.js index dd7977ac..dc092f96 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -129,7 +129,7 @@ async function initTabUrls() { } /** @param {chrome.webNavigation.GetAllFrameResultDetails[]} frames */ -function initPopup(frames) { +async function initPopup(frames) { installed = $('#installed'); setPopupWidth(); @@ -170,52 +170,52 @@ function initPopup(frames) { el.onclick = () => el.classList.toggle('expanded'); } - getActiveTab().then(function ping(tab, retryCountdown = 10) { - msg.sendTab(tab.id, {method: 'ping'}, {frameId: 0}) - .catch(() => false) - .then(pong => { - if (pong) { - return; - } - // FF and some Chrome forks (e.g. CentBrowser) implement tab-on-demand - // so we'll wait a bit to handle popup being invoked right after switching - if (retryCountdown > 0 && ( - tab.status !== 'complete' || - FIREFOX && tab.url === ABOUT_BLANK)) { - setTimeout(ping, 100, tab, --retryCountdown); - return; - } - const info = t.template.unreachableInfo; - if (!FIREFOX) { - // Chrome "Allow access to file URLs" in chrome://extensions message - info.appendChild($create('p', t('unreachableFileHint'))); - } - if (FIREFOX && tabURL.startsWith(URLS.browserWebStore)) { - $('label', info).textContent = t('unreachableAMO'); - const note = (FIREFOX < 59 ? t('unreachableAMOHintOldFF') : t('unreachableAMOHint')) + - (FIREFOX < 60 ? '' : '\n' + t('unreachableAMOHintNewFF')); - const renderToken = s => s[0] === '<' - ? $create('a', { - textContent: s.slice(1, -1), - onclick: handleEvent.copyContent, - href: '#', - className: 'copy', - tabIndex: 0, - title: t('copy'), - }) - : s; - const renderLine = line => $create('p', line.split(/(<.*?>)/).map(renderToken)); - const noteNode = $create('fragment', note.split('\n').map(renderLine)); - info.appendChild(noteNode); - } - // Inaccessible locally hosted file type, e.g. JSON, PDF, etc. - if (tabURL.length - tabURL.lastIndexOf('.') <= 5) { - info.appendChild($create('p', t('InaccessibleFileHint'))); - } - document.body.classList.add('unreachable'); - document.body.insertBefore(info, document.body.firstChild); - }); - }); + const isStore = tabURL.startsWith(URLS.browserWebStore); + if (isStore && !FIREFOX) { + blockPopup(); + return; + } + + for (let retryCountdown = 10; retryCountdown-- > 0;) { + const tab = await getActiveTab(); + if (await msg.sendTab(tab.id, {method: 'ping'}, {frameId: 0}).catch(() => {})) { + return; + } + if (tab.status === 'complete' && (!FIREFOX || tab.url !== ABOUT_BLANK)) { + break; + } + // FF and some Chrome forks (e.g. CentBrowser) implement tab-on-demand + // so we'll wait a bit to handle popup being invoked right after switching + await new Promise(resolve => setTimeout(resolve, 100)); + } + const info = t.template.unreachableInfo; + if (!FIREFOX) { + // Chrome "Allow access to file URLs" in chrome://extensions message + info.appendChild($create('p', t('unreachableFileHint'))); + } else if (isStore) { + $('label', info).textContent = t('unreachableAMO'); + const note = (FIREFOX < 59 ? t('unreachableAMOHintOldFF') : t('unreachableAMOHint')) + + (FIREFOX < 60 ? '' : '\n' + t('unreachableAMOHintNewFF')); + const renderToken = s => s[0] === '<' + ? $create('a', { + textContent: s.slice(1, -1), + onclick: handleEvent.copyContent, + href: '#', + className: 'copy', + tabIndex: 0, + title: t('copy'), + }) + : s; + const renderLine = line => $create('p', line.split(/(<.*?>)/).map(renderToken)); + const noteNode = $create('fragment', note.split('\n').map(renderLine)); + info.appendChild(noteNode); + } + // Inaccessible locally hosted file type, e.g. JSON, PDF, etc. + if (tabURL.length - tabURL.lastIndexOf('.') <= 5) { + info.appendChild($create('p', t('InaccessibleFileHint'))); + } + document.body.classList.add('unreachable'); + document.body.insertBefore(info, document.body.firstChild); } /** @param {chrome.webNavigation.GetAllFrameResultDetails} frame */ @@ -439,6 +439,7 @@ function createStyleElement(style) { const sel = 'span.frame-url'; const frameEl = $(sel, entry) || styleName.insertBefore($create(sel), styleName.lastChild); frameEl.title = frameUrl; + frameEl.onmousedown = handleEvent.maybeEdit; } entry.classList.toggle('frame', Boolean(frameUrl)); @@ -626,7 +627,8 @@ Object.assign(handleEvent, { return; } // open an editor on middleclick - if (event.target.matches('.entry, .style-name, .style-edit-link')) { + const el = event.target; + if (el.matches('.entry, .style-edit-link') || el.closest('.style-name')) { this.onmouseup = () => $('.style-edit-link', this).click(); this.oncontextmenu = event => event.preventDefault(); event.preventDefault(); @@ -634,7 +636,7 @@ Object.assign(handleEvent, { } // prevent the popup being opened in a background tab // when an irrelevant link was accidentally clicked - if (event.target.closest('a')) { + if (el.closest('a')) { event.preventDefault(); return; }