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",
"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": {
"message": "Add",
"description": "Used in various places for an action that adds something"

View File

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

View File

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

View File

@ -42,7 +42,6 @@
'popup.stylesFirst': true, // display enabled styles before disabled styles
'popup.autoResort': false, // auto resort styles after toggling
'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 */
'popup.findSort': 'u', // the inline style search sort order

View File

@ -196,15 +196,6 @@
<input id="disableAll" type="checkbox">
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
</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">
<a id="write-for-frames" title="&lsaquo;iframe&rsaquo;..." tabindex="0" hidden></a>
<span id="write-style-for" i18n="writeStyleFor"></span>
@ -212,15 +203,25 @@
</div>
<div id="popup-options">
<div class="split-btn">
<div class="split-btn" id="manage-split">
<button id="popup-manage-button" i18n="openManage, title:popupManageTooltip"
data-href="manage.html"></button
><button class="split-btn-pedal" i18n="menu-site:popupManageSiteStyles"></button>
</div>
<button id="popup-options-button" i18n="openOptions"></button>
<button id="popup-wiki-button"
i18n="linkStylusWiki, title:linkGetHelp"
data-href="https://github.com/openstyles/stylus/wiki"></button>
<div class="split-btn" id="find-split">
<button id="find-styles-btn" i18n="findStyles"></button
><button class="split-btn-pedal"
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 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;
}
#find-styles-link {
cursor: pointer;
margin-right: .5em;
}
.style-name:hover .checker:checked,
.style-name:hover .checker {
border-color: var(--c30);
@ -613,7 +608,7 @@ body.blocked #main-actions > :not(#disableAll-label) {
#popup-options .split-btn > :first-child {
width: calc(100% - 16px);
}
.blocked #popup-options .split-btn > :first-child {
.blocked #popup-options > * > :first-child {
width: 100%;
}
#popup-options button {
@ -626,12 +621,30 @@ body.blocked #main-actions > :not(#disableAll-label) {
margin-right: 4px;
}
#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 */
flex: 1 1 auto;
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;
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();
Object.assign($('#find-styles-link'), {
href: URLS.usoArchive + 'browse/styles',
async onclick(e) {
e.preventDefault();
await require(['/popup/search']);
Events.searchOnClick(this, e);
},
});
const elFind = $('#find-styles-btn');
elFind.onclick = async e => {
elFind.disabled = e.type === 'click';
await require(['/popup/search']);
Events.searchSite(e);
};
elFind.on('split-btn', elFind.onclick);
Object.assign($('#popup-manage-button'), {
onclick: Events.openManager,
oncontextmenu: Events.openManager,
}).on('split-btn', Events.openManager);
$('#popup-options-button').onclick = () => {
$('#options-btn').onclick = () => {
API.openManage({options: true});
window.close();
};
$('#popup-wiki-button').onclick = Events.openURLandHide;
$('#confirm').onclick = function (e) {
const {id} = this.dataset;
switch (e.target.dataset.cmd) {

View File

@ -2,7 +2,7 @@
/* global $entry tabURL */// popup.js
/* global API */// msg.js
/* global Events */
/* global FIREFOX URLS debounce download tryCatch */// toolbox.js
/* global FIREFOX URLS debounce download tryURL */// toolbox.js
/* global prefs */
/* global t */// localization.js
'use strict';
@ -75,104 +75,98 @@
const show = sel => $classList(sel).remove('hidden');
const hide = sel => $classList(sel).add('hidden');
Object.assign(Events, {
/**
* @param {HTMLAnchorElement} a
* @param {Event} event
*/
searchOnClick(a, event) {
if (!prefs.get('popup.findStylesInline') || dom.container) {
// use a less specific category if the inline search wasn't used yet
if (!category) calcCategory({retry: 1});
const search = [
category ? '#' + category : '',
$('#search-query').value,
].filter(Boolean).join(' ');
a.search = search ? 'search=' + encodeURIComponent(search) : '';
Events.openURLandHide.call(a, event);
return;
}
a.textContent = a.title;
a.title = '';
init();
calcCategory();
ready = start();
},
Events.searchSite = event => {
// use a less specific category if the inline search wasn't used yet
if (!category) calcCategory({retry: 1});
const add = (prefix, str) => str ? prefix + str : '';
const where = event.detail;
const q = encodeURIComponent($('#search-query').value.trim());
const catQ = category + add('+', q);
const href =
where === 'uso' &&
`${URLS.uso}styles/browse${q ? `?search_terms=${catQ}` : `/${category}`}` ||
where === 'usoa' &&
`${URLS.usoArchive}browse/styles?search=%23${catQ}` ||
where === 'usw' &&
`${URLS.usw}search?q=${catQ}` ||
where === 'gf' &&
'https://greasyfork.org/' + ($.root.lang.split('-')[0] || 'en') +
`/scripts/by-site/${tryURL(tabURL).hostname}?language=css${add('&q=', q)}`;
Events.openURLandHide.call({href}, event);
};
$('#search-globals').onchange = function () {
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() {
setTimeout(() => document.body.classList.add('search-results-shown'));
hide('#find-styles-inline-group');
$('#search-globals').onchange = function () {
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;
}
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);
}
});
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);
}
});
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);
}
});
}
calcCategory();
ready = start();
function next() {
displayedPage = Math.min(totalPages, displayedPage + 1);
@ -196,9 +190,7 @@
}
async function start() {
show(dom.container);
show(dom.list);
hide(dom.error);
resetUI.timer = setTimeout(resetUI, 500);
try {
results = [];
for (let retry = 0; !results.length && retry <= 2; retry++) {
@ -217,6 +209,15 @@
} catch (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() {
@ -481,9 +482,9 @@
* @returns {boolean} true if the category has actually changed
*/
function calcCategory({retry} = {}) {
const u = tryCatch(() => new URL(tabURL));
const u = tryURL(tabURL);
const old = category;
if (!u) {
if (!u.href) {
// Invalid URL
category = '';
} else if (u.protocol === 'file:') {