add USA/USW/US/GF splitter to Find styles

This commit is contained in:
tophf 2022-02-21 00:02:42 +03:00
parent 268c7b758b
commit bd0e8273c1
8 changed files with 151 additions and 149 deletions

View File

@ -451,18 +451,6 @@
"message": "Find styles", "message": "Find styles",
"description": "Text for a link that gets a list of styles for the current site" "description": "Text for a link that gets a list of styles for the current site"
}, },
"findStylesForSite": {
"message": "Find more styles for this site",
"description": "Text for a link that gets a list of styles for the current site"
},
"findStylesInline": {
"message": "Inline",
"description": "Text for a checkbox that opens search results 'inline' (within the Stylus popup window)"
},
"findStylesInlineTooltip": {
"message": "Display search results inside this window.",
"description": "Text for a checkbox that displays search results within the Stylus popup."
},
"genericAdd": { "genericAdd": {
"message": "Add", "message": "Add",
"description": "Used in various places for an action that adds something" "description": "Used in various places for an action that adds something"

View File

@ -23,9 +23,6 @@
.style-settings input:disabled ~ label { .style-settings input:disabled ~ label {
opacity: .5; opacity: .5;
} }
.style-settings .rel {
position: relative;
}
.style-settings .w100 { .style-settings .w100 {
display: block; display: block;
width: 100%; width: 100%;

View File

@ -297,6 +297,12 @@ summary {
.hidden { .hidden {
display: none !important; display: none !important;
} }
.rel {
position: relative;
}
.abs {
position: absolute;
}
:focus, :focus,
.CodeMirror-focused, .CodeMirror-focused,

View File

@ -42,7 +42,6 @@
'popup.stylesFirst': true, // display enabled styles before disabled styles 'popup.stylesFirst': true, // display enabled styles before disabled styles
'popup.autoResort': false, // auto resort styles after toggling 'popup.autoResort': false, // auto resort styles after toggling
'popup.borders': false, // add white borders on the sides 'popup.borders': false, // add white borders on the sides
'popup.findStylesInline': true, // use the inline style search
/** @type {'n' | 'u' | 't' | 'w' | 'r'} see IndexEntry */ /** @type {'n' | 'u' | 't' | 'w' | 'r'} see IndexEntry */
'popup.findSort': 'u', // the inline style search sort order 'popup.findSort': 'u', // the inline style search sort order

View File

@ -196,15 +196,6 @@
<input id="disableAll" type="checkbox"> <input id="disableAll" type="checkbox">
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg> <svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
</label> </label>
<div id="find-styles">
<a id="find-styles-link" i18n="findStyles, title:findStylesForSite"
href="https://to.be.replaced.on.click/" target="_blank"></a>
<label id="find-styles-inline-group" class="checkbox-wrapper" i18n="title:findStylesInlineTooltip">
<input id="popup.findStylesInline" class="checker" type="checkbox">
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
<span i18n="findStylesInline"></span>
</label>
</div>
<div id="write-style"> <div id="write-style">
<a id="write-for-frames" title="&lsaquo;iframe&rsaquo;..." tabindex="0" hidden></a> <a id="write-for-frames" title="&lsaquo;iframe&rsaquo;..." tabindex="0" hidden></a>
<span id="write-style-for" i18n="writeStyleFor"></span> <span id="write-style-for" i18n="writeStyleFor"></span>
@ -212,15 +203,25 @@
</div> </div>
<div id="popup-options"> <div id="popup-options">
<div class="split-btn"> <div class="split-btn" id="manage-split">
<button id="popup-manage-button" i18n="openManage, title:popupManageTooltip" <button id="popup-manage-button" i18n="openManage, title:popupManageTooltip"
data-href="manage.html"></button data-href="manage.html"></button
><button class="split-btn-pedal" i18n="menu-site:popupManageSiteStyles"></button> ><button class="split-btn-pedal" i18n="menu-site:popupManageSiteStyles"></button>
</div> </div>
<button id="popup-options-button" i18n="openOptions"></button> <div class="split-btn" id="find-split">
<button id="popup-wiki-button" <button id="find-styles-btn" i18n="findStyles"></button
i18n="linkStylusWiki, title:linkGetHelp" ><button class="split-btn-pedal"
data-href="https://github.com/openstyles/stylus/wiki"></button> menu-usoa="UserStyles Archive"
menu-usw="UserStyles World"
menu-uso="UserStyles"
menu-gf="GreasyFork"></button>
</div>
<button id="options-btn" i18n="title:openOptions" class="rel">
<svg class="svg-icon config abs"><use xlink:href="#svg-icon-config"></use></svg>
</button>
<a href="https://github.com/openstyles/stylus/wiki" target="_blank">
<button id="popup-wiki-button" i18n="linkStylusWiki, title:linkGetHelp"></button>
</a>
</div> </div>
<div id="search-results-error" class="hidden"></div> <div id="search-results-error" class="hidden"></div>

View File

@ -64,11 +64,6 @@ body > div:not(#installed):not(#message-box):not(.colorpicker-popup) {
font-weight: bold; font-weight: bold;
} }
#find-styles-link {
cursor: pointer;
margin-right: .5em;
}
.style-name:hover .checker:checked, .style-name:hover .checker:checked,
.style-name:hover .checker { .style-name:hover .checker {
border-color: var(--c30); border-color: var(--c30);
@ -613,7 +608,7 @@ body.blocked #main-actions > :not(#disableAll-label) {
#popup-options .split-btn > :first-child { #popup-options .split-btn > :first-child {
width: calc(100% - 16px); width: calc(100% - 16px);
} }
.blocked #popup-options .split-btn > :first-child { .blocked #popup-options > * > :first-child {
width: 100%; width: 100%;
} }
#popup-options button { #popup-options button {
@ -626,12 +621,30 @@ body.blocked #main-actions > :not(#disableAll-label) {
margin-right: 4px; margin-right: 4px;
} }
#popup-options > *, #popup-options > *,
#popup-manage-button { #popup-options .split-btn > :first-child {
/* several languages have labels of wildly different lengths so we try to maintain the proportion */ /* several languages have labels of wildly different lengths so we try to maintain the proportion */
flex: 1 1 auto; flex: 1 1 auto;
min-width: 2em; min-width: 2em;
} }
html:not(.styles-last) #popup-manage-button ~ .split-btn-menu { .blocked #find-split,
.blocked #options-btn svg,
body:not(.blocked) #popup-options a[href*="wiki"] {
display: none;
}
#options-btn::after {
content: '\A0';
}
.blocked #options-btn::after {
content: attr(title);
}
#options-btn svg {
left: 0;
right: 0;
margin: auto;
fill: transparent;
stroke: currentColor;
}
html:not(.styles-last) #popup-options .split-btn-menu {
bottom: 0; bottom: 0;
transform: translateY(-20px); /* global button style: 13(font) * 1.2(line) + 4(pad) + 2(border) */ transform: translateY(-20px); /* global button style: 13(font) * 1.2(line) + 4(pad) + 2(border) */
} }

View File

@ -90,27 +90,24 @@ async function initPopup(frames) {
}; };
setupLivePrefs(); setupLivePrefs();
Object.assign($('#find-styles-link'), { const elFind = $('#find-styles-btn');
href: URLS.usoArchive + 'browse/styles', elFind.onclick = async e => {
async onclick(e) { elFind.disabled = e.type === 'click';
e.preventDefault(); await require(['/popup/search']);
await require(['/popup/search']); Events.searchSite(e);
Events.searchOnClick(this, e); };
}, elFind.on('split-btn', elFind.onclick);
});
Object.assign($('#popup-manage-button'), { Object.assign($('#popup-manage-button'), {
onclick: Events.openManager, onclick: Events.openManager,
oncontextmenu: Events.openManager, oncontextmenu: Events.openManager,
}).on('split-btn', Events.openManager); }).on('split-btn', Events.openManager);
$('#popup-options-button').onclick = () => { $('#options-btn').onclick = () => {
API.openManage({options: true}); API.openManage({options: true});
window.close(); window.close();
}; };
$('#popup-wiki-button').onclick = Events.openURLandHide;
$('#confirm').onclick = function (e) { $('#confirm').onclick = function (e) {
const {id} = this.dataset; const {id} = this.dataset;
switch (e.target.dataset.cmd) { switch (e.target.dataset.cmd) {

View File

@ -2,7 +2,7 @@
/* global $entry tabURL */// popup.js /* global $entry tabURL */// popup.js
/* global API */// msg.js /* global API */// msg.js
/* global Events */ /* global Events */
/* global FIREFOX URLS debounce download tryCatch */// toolbox.js /* global FIREFOX URLS debounce download tryURL */// toolbox.js
/* global prefs */ /* global prefs */
/* global t */// localization.js /* global t */// localization.js
'use strict'; 'use strict';
@ -75,104 +75,98 @@
const show = sel => $classList(sel).remove('hidden'); const show = sel => $classList(sel).remove('hidden');
const hide = sel => $classList(sel).add('hidden'); const hide = sel => $classList(sel).add('hidden');
Object.assign(Events, { Events.searchSite = event => {
/** // use a less specific category if the inline search wasn't used yet
* @param {HTMLAnchorElement} a if (!category) calcCategory({retry: 1});
* @param {Event} event const add = (prefix, str) => str ? prefix + str : '';
*/ const where = event.detail;
searchOnClick(a, event) { const q = encodeURIComponent($('#search-query').value.trim());
if (!prefs.get('popup.findStylesInline') || dom.container) { const catQ = category + add('+', q);
// use a less specific category if the inline search wasn't used yet const href =
if (!category) calcCategory({retry: 1}); where === 'uso' &&
const search = [ `${URLS.uso}styles/browse${q ? `?search_terms=${catQ}` : `/${category}`}` ||
category ? '#' + category : '', where === 'usoa' &&
$('#search-query').value, `${URLS.usoArchive}browse/styles?search=%23${catQ}` ||
].filter(Boolean).join(' '); where === 'usw' &&
a.search = search ? 'search=' + encodeURIComponent(search) : ''; `${URLS.usw}search?q=${catQ}` ||
Events.openURLandHide.call(a, event); where === 'gf' &&
return; 'https://greasyfork.org/' + ($.root.lang.split('-')[0] || 'en') +
} `/scripts/by-site/${tryURL(tabURL).hostname}?language=css${add('&q=', q)}`;
a.textContent = a.title; Events.openURLandHide.call({href}, event);
a.title = ''; };
init();
calcCategory(); $('#search-globals').onchange = function () {
ready = start(); searchGlobals = this.checked;
}, ready = ready.then(start);
};
$('#search-query').oninput = function () {
query = [];
const text = this.value.trim().toLocaleLowerCase();
const thisYear = new Date().getFullYear();
for (let re = /"(.+?)"|(\S+)/g, m; (m = re.exec(text));) {
const n = Number(m[2]);
query.push(n >= 2000 && n <= thisYear ? n : m[1] || m[2]);
}
if (category === STYLUS_CATEGORY && !query.includes('stylus')) {
query.push('stylus');
}
ready = ready.then(start);
};
$('#search-order').value = order;
$('#search-order').onchange = function () {
order = this.value;
prefs.set('popup.findSort', order);
results.sort(comparator);
render();
};
dom.list = $('#search-results-list');
dom.container = $('#search-results');
dom.container.dataset.empty = '';
dom.error = $('#search-results-error');
dom.nav = {};
const navOnClick = {prev, next};
for (const place of ['top', 'bottom']) {
const nav = $(`.search-results-nav[data-type="${place}"]`);
nav.appendChild(t.template.searchNav.cloneNode(true));
dom.nav[place] = nav;
for (const child of $$('[data-type]', nav)) {
const type = child.dataset.type;
child.onclick = navOnClick[type];
nav['_' + type] = child;
}
}
if (FIREFOX) {
let lastShift;
window.on('resize', () => {
const scrollbarWidth = window.innerWidth - document.scrollingElement.clientWidth;
const shift = document.body.getBoundingClientRect().left;
if (!scrollbarWidth || shift === lastShift) return;
lastShift = shift;
document.body.style.setProperty('padding',
`0 ${scrollbarWidth + shift}px 0 ${-shift}px`, 'important');
}, {passive: true});
}
window.on('styleDeleted', ({detail: {style: {id}}}) => {
restoreScrollPosition();
const result = results.find(r => r.installedStyleId === id);
if (result) {
clearTimeout(result.pingbackTimer);
renderActionButtons(result.i, -1);
}
}); });
function init() { window.on('styleAdded', async ({detail: {style}}) => {
setTimeout(() => document.body.classList.add('search-results-shown')); restoreScrollPosition();
hide('#find-styles-inline-group'); const id = calcId(style) || calcId(await API.styles.get(style.id));
$('#search-globals').onchange = function () { if (id && results.find(r => r.i === id)) {
searchGlobals = this.checked; renderActionButtons(id, style.id);
ready = ready.then(start);
};
$('#search-query').oninput = function () {
query = [];
const text = this.value.trim().toLocaleLowerCase();
const thisYear = new Date().getFullYear();
for (let re = /"(.+?)"|(\S+)/g, m; (m = re.exec(text));) {
const n = Number(m[2]);
query.push(n >= 2000 && n <= thisYear ? n : m[1] || m[2]);
}
if (category === STYLUS_CATEGORY && !query.includes('stylus')) {
query.push('stylus');
}
ready = ready.then(start);
};
$('#search-order').value = order;
$('#search-order').onchange = function () {
order = this.value;
prefs.set('popup.findSort', order);
results.sort(comparator);
render();
};
dom.list = $('#search-results-list');
dom.container = $('#search-results');
dom.container.dataset.empty = '';
dom.error = $('#search-results-error');
dom.nav = {};
const navOnClick = {prev, next};
for (const place of ['top', 'bottom']) {
const nav = $(`.search-results-nav[data-type="${place}"]`);
nav.appendChild(t.template.searchNav.cloneNode(true));
dom.nav[place] = nav;
for (const child of $$('[data-type]', nav)) {
const type = child.dataset.type;
child.onclick = navOnClick[type];
nav['_' + type] = child;
}
} }
});
if (FIREFOX) { calcCategory();
let lastShift; ready = start();
window.on('resize', () => {
const scrollbarWidth = window.innerWidth - document.scrollingElement.clientWidth;
const shift = document.body.getBoundingClientRect().left;
if (!scrollbarWidth || shift === lastShift) return;
lastShift = shift;
document.body.style.setProperty('padding',
`0 ${scrollbarWidth + shift}px 0 ${-shift}px`, 'important');
}, {passive: true});
}
window.on('styleDeleted', ({detail: {style: {id}}}) => {
restoreScrollPosition();
const result = results.find(r => r.installedStyleId === id);
if (result) {
clearTimeout(result.pingbackTimer);
renderActionButtons(result.i, -1);
}
});
window.on('styleAdded', async ({detail: {style}}) => {
restoreScrollPosition();
const id = calcId(style) || calcId(await API.styles.get(style.id));
if (id && results.find(r => r.i === id)) {
renderActionButtons(id, style.id);
}
});
}
function next() { function next() {
displayedPage = Math.min(totalPages, displayedPage + 1); displayedPage = Math.min(totalPages, displayedPage + 1);
@ -196,9 +190,7 @@
} }
async function start() { async function start() {
show(dom.container); resetUI.timer = setTimeout(resetUI, 500);
show(dom.list);
hide(dom.error);
try { try {
results = []; results = [];
for (let retry = 0; !results.length && retry <= 2; retry++) { for (let retry = 0; !results.length && retry <= 2; retry++) {
@ -217,6 +209,15 @@
} catch (reason) { } catch (reason) {
error(reason); error(reason);
} }
clearTimeout(resetUI.timer);
resetUI();
}
function resetUI() {
document.body.classList.add('search-results-shown');
show(dom.container);
show(dom.list);
hide(dom.error);
} }
function render() { function render() {
@ -481,9 +482,9 @@
* @returns {boolean} true if the category has actually changed * @returns {boolean} true if the category has actually changed
*/ */
function calcCategory({retry} = {}) { function calcCategory({retry} = {}) {
const u = tryCatch(() => new URL(tabURL)); const u = tryURL(tabURL);
const old = category; const old = category;
if (!u) { if (!u.href) {
// Invalid URL // Invalid URL
category = ''; category = '';
} else if (u.protocol === 'file:') { } else if (u.protocol === 'file:') {