switch to USO-archive for inline search in popup
feature: retry sub.domain.tld as domain.tld if no styles are found old bug fix: show newly added style in popup dedupe/simplify bits of popup.js
This commit is contained in:
parent
5196f96ee3
commit
0162f39163
|
@ -1181,6 +1181,10 @@
|
||||||
"message": "Number of matches in code and applies-to values",
|
"message": "Number of matches in code and applies-to values",
|
||||||
"description": "Tooltip for the number of found search results in the editor shown on Ctrl-F"
|
"description": "Tooltip for the number of found search results in the editor shown on Ctrl-F"
|
||||||
},
|
},
|
||||||
|
"searchStyleQueryHint": {
|
||||||
|
"message": "Search style names case-insensitively:\nsome words - all words in any order\n\"some phrase\" - this exact phrase without quotes\n2020 - a year like this also shows styles updated in 2020",
|
||||||
|
"description": "Tooltip shown for the text input in the popup's inline style finder"
|
||||||
|
},
|
||||||
"searchRegexp": {
|
"searchRegexp": {
|
||||||
"message": "Use /re/ syntax for regexp search",
|
"message": "Use /re/ syntax for regexp search",
|
||||||
"description": "Label after the search input field in the editor shown on Ctrl-F"
|
"description": "Label after the search input field in the editor shown on Ctrl-F"
|
||||||
|
|
|
@ -62,7 +62,15 @@ const URLS = {
|
||||||
// TODO: remove when "minimum_chrome_version": "61" or higher
|
// TODO: remove when "minimum_chrome_version": "61" or higher
|
||||||
chromeProtectsNTP: CHROME >= 61,
|
chromeProtectsNTP: CHROME >= 61,
|
||||||
|
|
||||||
userstylesOrgJson: 'https://userstyles.org/styles/chrome/',
|
uso: 'https://userstyles.org/',
|
||||||
|
usoJson: 'https://userstyles.org/styles/chrome/',
|
||||||
|
|
||||||
|
usoArchive: 'https://33kk.github.io/uso-archive/',
|
||||||
|
usoArchiveRaw: 'https://raw.githubusercontent.com/33kk/uso-archive/flomaster/data/',
|
||||||
|
extractUsoArchiveId: url =>
|
||||||
|
url &&
|
||||||
|
url.startsWith(URLS.usoArchiveRaw) &&
|
||||||
|
parseInt(url.match(/\/(\d+)\.user\.css|$/)[1]),
|
||||||
|
|
||||||
supported: url => (
|
supported: url => (
|
||||||
url.startsWith('http') && (FIREFOX || !url.startsWith(URLS.browserWebStore)) ||
|
url.startsWith('http') && (FIREFOX || !url.startsWith(URLS.browserWebStore)) ||
|
||||||
|
@ -438,7 +446,7 @@ function download(url, {
|
||||||
function collapseUsoVars(url) {
|
function collapseUsoVars(url) {
|
||||||
if (queryPos < 0 ||
|
if (queryPos < 0 ||
|
||||||
url.length < 2000 ||
|
url.length < 2000 ||
|
||||||
!url.startsWith(URLS.userstylesOrgJson) ||
|
!url.startsWith(URLS.usoJson) ||
|
||||||
!/^get$/i.test(method)) {
|
!/^get$/i.test(method)) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
18
popup.html
18
popup.html
|
@ -120,9 +120,7 @@
|
||||||
<div class="search-result-actions">
|
<div class="search-result-actions">
|
||||||
<button class="search-result-install hidden" i18n-text="installButton"></button>
|
<button class="search-result-install hidden" i18n-text="installButton"></button>
|
||||||
<button class="search-result-uninstall hidden" i18n-text="deleteStyleLabel"></button>
|
<button class="search-result-uninstall hidden" i18n-text="deleteStyleLabel"></button>
|
||||||
<button class="search-result-customize hidden"
|
<button class="search-result-customize hidden" i18n-text="configureStyle"></button>
|
||||||
i18n-text="configureStyle"
|
|
||||||
i18n-title="configureStyleOnHomepage"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<dl class="search-result-meta">
|
<dl class="search-result-meta">
|
||||||
<div data-type="author">
|
<div data-type="author">
|
||||||
|
@ -254,6 +252,20 @@
|
||||||
<div id="search-results-error" class="hidden"></div>
|
<div id="search-results-error" class="hidden"></div>
|
||||||
<div id="search-results" class="hidden">
|
<div id="search-results" class="hidden">
|
||||||
<div class="search-results-nav" data-type="top"></div>
|
<div class="search-results-nav" data-type="top"></div>
|
||||||
|
<div id="search-params">
|
||||||
|
<input id="search-query" type="search" i18n-placeholder="search"
|
||||||
|
i18n-title="searchStyleQueryHint">
|
||||||
|
<div class="select-resizer">
|
||||||
|
<select id="search-order" i18n-title="sortStylesHelpTitle">
|
||||||
|
<option value="n" i18n-text="genericTitle">
|
||||||
|
<option value="u" i18n-text="searchResultUpdated">
|
||||||
|
<option value="t" i18n-text="searchResultInstallCount">
|
||||||
|
<option value="w" i18n-text="searchResultWeeklyCount">
|
||||||
|
<option value="r" i18n-text="searchResultRating">
|
||||||
|
</select>
|
||||||
|
<svg class="svg-icon select-arrow"><use xlink:href="#svg-icon-select-arrow"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="search-results-list"></div>
|
<div id="search-results-list"></div>
|
||||||
<div class="search-results-nav" data-type="bottom"></div>
|
<div class="search-results-nav" data-type="bottom"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,7 +33,8 @@ const hotkeys = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKeyDown(event) {
|
function onKeyDown(event) {
|
||||||
if (event.ctrlKey || event.altKey || event.metaKey || !enabled) {
|
if (event.ctrlKey || event.altKey || event.metaKey || !enabled ||
|
||||||
|
/^(text|search)$/.test((document.activeElement || {}).type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let entry;
|
let entry;
|
||||||
|
|
|
@ -13,7 +13,8 @@ const handleEvent = {};
|
||||||
|
|
||||||
const ABOUT_BLANK = 'about:blank';
|
const ABOUT_BLANK = 'about:blank';
|
||||||
const ENTRY_ID_PREFIX_RAW = 'style-';
|
const ENTRY_ID_PREFIX_RAW = 'style-';
|
||||||
const ENTRY_ID_PREFIX = '#' + ENTRY_ID_PREFIX_RAW;
|
|
||||||
|
$.entry = styleOrId => $(`#${ENTRY_ID_PREFIX_RAW}${styleOrId.id || styleOrId}`);
|
||||||
|
|
||||||
if (CHROME >= 66 && CHROME <= 69) { // Chrome 66-69 adds a gap, https://crbug.com/821143
|
if (CHROME >= 66 && CHROME <= 69) { // Chrome 66-69 adds a gap, https://crbug.com/821143
|
||||||
document.head.appendChild($create('style', 'html { overflow: overlay }'));
|
document.head.appendChild($create('style', 'html { overflow: overlay }'));
|
||||||
|
@ -27,7 +28,7 @@ initTabUrls()
|
||||||
onDOMready().then(() => initPopup(frames)),
|
onDOMready().then(() => initPopup(frames)),
|
||||||
...frames
|
...frames
|
||||||
.filter(f => f.url && !f.isDupe)
|
.filter(f => f.url && !f.isDupe)
|
||||||
.map(({url}) => API.getStylesByUrl(url).then(styles => ({styles, url}))),
|
.map(({url}) => getStyleDataMerged(url).then(styles => ({styles, url}))),
|
||||||
]))
|
]))
|
||||||
.then(([, ...results]) => {
|
.then(([, ...results]) => {
|
||||||
if (results[0]) {
|
if (results[0]) {
|
||||||
|
@ -53,17 +54,19 @@ if (CHROME_HAS_BORDER_BUG) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRuntimeMessage(msg) {
|
function onRuntimeMessage(msg) {
|
||||||
|
if (!tabURL) return;
|
||||||
|
let ready = Promise.resolve();
|
||||||
switch (msg.method) {
|
switch (msg.method) {
|
||||||
case 'styleAdded':
|
case 'styleAdded':
|
||||||
case 'styleUpdated':
|
case 'styleUpdated':
|
||||||
if (msg.reason === 'editPreview' || msg.reason === 'editPreviewEnd') return;
|
if (msg.reason === 'editPreview' || msg.reason === 'editPreviewEnd') return;
|
||||||
handleUpdate(msg);
|
ready = handleUpdate(msg);
|
||||||
break;
|
break;
|
||||||
case 'styleDeleted':
|
case 'styleDeleted':
|
||||||
handleDelete(msg.style.id);
|
handleDelete(msg.style.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dispatchEvent(new CustomEvent(msg.method, {detail: msg}));
|
ready.then(() => dispatchEvent(new CustomEvent(msg.method, {detail: msg})));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,8 +144,7 @@ function initPopup(frames) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tabURL) {
|
if (!tabURL) {
|
||||||
document.body.classList.add('blocked');
|
blockPopup();
|
||||||
document.body.insertBefore(template.unavailableInfo, document.body.firstChild);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,24 +317,30 @@ function showStyles(frameResults) {
|
||||||
const entries = new Map();
|
const entries = new Map();
|
||||||
frameResults.forEach(({styles = [], url}, index) => {
|
frameResults.forEach(({styles = [], url}, index) => {
|
||||||
styles.forEach(style => {
|
styles.forEach(style => {
|
||||||
const {id} = style.data;
|
const {id} = style;
|
||||||
if (!entries.has(id)) {
|
if (!entries.has(id)) {
|
||||||
style.frameUrl = index === 0 ? '' : url;
|
style.frameUrl = index === 0 ? '' : url;
|
||||||
entries.set(id, createStyleElement(Object.assign(style.data, style)));
|
entries.set(id, createStyleElement(style));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (entries.size) {
|
if (entries.size) {
|
||||||
installed.append(...sortStyles([...entries.values()]));
|
resortEntries([...entries.values()]);
|
||||||
} else {
|
} else {
|
||||||
installed.appendChild(template.noStyles.cloneNode(true));
|
installed.appendChild(template.noStyles);
|
||||||
}
|
}
|
||||||
window.dispatchEvent(new Event('showStyles:done'));
|
window.dispatchEvent(new Event('showStyles:done'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resortEntries(entries) {
|
||||||
|
// `entries` is specified only at startup, after that we respect the prefs
|
||||||
|
if (entries || prefs.get('popup.autoResort')) {
|
||||||
|
installed.append(...sortStyles(entries || $$('.entry', installed)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createStyleElement(style) {
|
function createStyleElement(style) {
|
||||||
let entry = $(ENTRY_ID_PREFIX + style.id);
|
let entry = $.entry(style);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = template.style.cloneNode(true);
|
entry = template.style.cloneNode(true);
|
||||||
entry.setAttribute('style-id', style.id);
|
entry.setAttribute('style-id', style.id);
|
||||||
|
@ -469,11 +477,7 @@ Object.assign(handleEvent, {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
API
|
API
|
||||||
.toggleStyle(handleEvent.getClickedStyleId(event), this.checked)
|
.toggleStyle(handleEvent.getClickedStyleId(event), this.checked)
|
||||||
.then(() => {
|
.then(() => resortEntries());
|
||||||
if (prefs.get('popup.autoResort')) {
|
|
||||||
installed.append(...sortStyles($$('.entry', installed)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleExclude(event, type) {
|
toggleExclude(event, type) {
|
||||||
|
@ -672,38 +676,25 @@ Object.assign(handleEvent, {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function handleUpdate({style, reason}) {
|
async function handleUpdate({style, reason}) {
|
||||||
if (!tabURL) return;
|
if (reason !== 'toggle' || !$.entry(style)) {
|
||||||
|
style = await getStyleDataMerged(tabURL, style.id);
|
||||||
fetchStyle()
|
if (!style) return;
|
||||||
.then(style => {
|
|
||||||
if (!style) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ($(ENTRY_ID_PREFIX + style.id)) {
|
|
||||||
createStyleElement(style);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
document.body.classList.remove('blocked');
|
|
||||||
$$.remove('.blocked-info, #no-styles');
|
|
||||||
createStyleElement(style);
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
|
|
||||||
function fetchStyle() {
|
|
||||||
if (reason === 'toggle' && $(ENTRY_ID_PREFIX + style.id)) {
|
|
||||||
return Promise.resolve(style);
|
|
||||||
}
|
|
||||||
return API.getStylesByUrl(tabURL, style.id)
|
|
||||||
.then(([result]) => result && Object.assign(result.data, result));
|
|
||||||
}
|
}
|
||||||
|
const el = createStyleElement(style);
|
||||||
|
if (!el.parentNode) {
|
||||||
|
installed.appendChild(el);
|
||||||
|
blockPopup(false);
|
||||||
|
}
|
||||||
|
resortEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleDelete(id) {
|
function handleDelete(id) {
|
||||||
$.remove(ENTRY_ID_PREFIX + id);
|
const el = $.entry(id);
|
||||||
if (!$('.entry')) {
|
if (el) {
|
||||||
installed.appendChild(template.noStyles.cloneNode(true));
|
el.remove();
|
||||||
|
if (!$('.entry')) installed.appendChild(template.noStyles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,3 +712,21 @@ function waitForTabUrlFF(tab) {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merges the extra props from API into style data.
|
||||||
|
* When `id` is specified returns a single object otherwise an array */
|
||||||
|
async function getStyleDataMerged(url, id) {
|
||||||
|
const styles = (await API.getStylesByUrl(url, id))
|
||||||
|
.map(r => Object.assign(r.data, r));
|
||||||
|
return id ? styles[0] : styles;
|
||||||
|
}
|
||||||
|
|
||||||
|
function blockPopup(isBlocked = true) {
|
||||||
|
document.body.classList.toggle('blocked', isBlocked);
|
||||||
|
if (isBlocked) {
|
||||||
|
document.body.prepend(template.unavailableInfo);
|
||||||
|
} else {
|
||||||
|
template.unavailableInfo.remove();
|
||||||
|
template.noStyles.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -54,21 +54,15 @@ body.search-results-shown {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result .lds-spinner {
|
#search-results .lds-spinner {
|
||||||
transform: scale(.5);
|
transform: scale(.5);
|
||||||
filter: invert(1) drop-shadow(1px 1px 3px #000);
|
filter: invert(1) drop-shadow(1px 1px 3px #000);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-empty .lds-spinner {
|
#search-results .search-result-empty .lds-spinner {
|
||||||
transform: scale(.5);
|
|
||||||
filter: opacity(.2);
|
filter: opacity(.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-fadein {
|
|
||||||
animation: fadein 1s;
|
|
||||||
animation-fill-mode: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-result-screenshot {
|
.search-result-screenshot {
|
||||||
height: 140px;
|
height: 140px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -257,6 +251,18 @@ body.search-results-shown {
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-params {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-query {
|
||||||
|
min-width: 3em;
|
||||||
|
margin-right: .5em;
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/* spinner: https://github.com/loadingio/css-spinner */
|
/* spinner: https://github.com/loadingio/css-spinner */
|
||||||
.lds-spinner {
|
.lds-spinner {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user