lazy-load favicons
This commit is contained in:
parent
d048c480c3
commit
513ced6d57
|
@ -666,7 +666,7 @@ a:hover {
|
||||||
transition: opacity .5s, filter .5s;
|
transition: opacity .5s, filter .5s;
|
||||||
/* workaround for the buggy CSS filter: images in the hidden overflow are shown on Mac */
|
/* workaround for the buggy CSS filter: images in the hidden overflow are shown on Mac */
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
display: none;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newUI .favicons-grayed .target img {
|
.newUI .favicons-grayed .target img {
|
||||||
|
@ -679,7 +679,7 @@ a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.newUI .has-favicons .target img[src] {
|
.newUI .has-favicons .target img[src] {
|
||||||
display: inline;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newUI .entry:hover .target img {
|
.newUI .entry:hover .target img {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global $ $$ animateElement scrollElementIntoView */// dom.js
|
/* global $$ $ $create animateElement scrollElementIntoView */// dom.js
|
||||||
/* global API */// msg.js
|
/* global API */// msg.js
|
||||||
/* global URLS debounce isEmptyObj sessionStore */// toolbox.js
|
/* global URLS debounce isEmptyObj sessionStore */// toolbox.js
|
||||||
/* global filterAndAppend */// filters.js
|
/* global filterAndAppend */// filters.js
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
const ENTRY_ID_PREFIX_RAW = 'style-';
|
const ENTRY_ID_PREFIX_RAW = 'style-';
|
||||||
const TARGET_TYPES = ['domains', 'urls', 'urlPrefixes', 'regexps'];
|
const TARGET_TYPES = ['domains', 'urls', 'urlPrefixes', 'regexps'];
|
||||||
const OWN_ICON = chrome.runtime.getManifest().icons['16'];
|
const OWN_ICON = chrome.runtime.getURL(chrome.runtime.getManifest().icons['16']);
|
||||||
const AGES = [
|
const AGES = [
|
||||||
[24, 'h', t('dateAbbrHour', '\x01')],
|
[24, 'h', t('dateAbbrHour', '\x01')],
|
||||||
[30, 'd', t('dateAbbrDay', '\x01')],
|
[30, 'd', t('dateAbbrDay', '\x01')],
|
||||||
|
@ -18,6 +18,32 @@ const AGES = [
|
||||||
[Infinity, 'y', t('dateAbbrYear', '\x01')],
|
[Infinity, 'y', t('dateAbbrYear', '\x01')],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const proto = HTMLImageElement.prototype;
|
||||||
|
if ('loading' in proto) return;
|
||||||
|
const pSrc = Object.getOwnPropertyDescriptor(proto, 'src');
|
||||||
|
const xo = new IntersectionObserver(entries => {
|
||||||
|
for (const e of entries) {
|
||||||
|
if (e.isIntersecting) {
|
||||||
|
const el = e.target;
|
||||||
|
pSrc.set.call(el, el.dataset.src);
|
||||||
|
xo.unobserve(el);
|
||||||
|
delete el.dataset.src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(proto, 'src', Object.assign({}, pSrc, {
|
||||||
|
set(val) {
|
||||||
|
if (this.loading === 'lazy') {
|
||||||
|
this.dataset.src = val;
|
||||||
|
xo.observe(this);
|
||||||
|
} else {
|
||||||
|
pSrc.set.call(this, val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
})();
|
||||||
|
|
||||||
let elementParts;
|
let elementParts;
|
||||||
|
|
||||||
function $entry(styleOrId, root = installed) {
|
function $entry(styleOrId, root = installed) {
|
||||||
|
@ -215,19 +241,14 @@ function getFaviconSrc(container = installed) {
|
||||||
favicon = targetValue.includes('://') && targetValue.match(regexpMatchDomain);
|
favicon = targetValue.includes('://') && targetValue.match(regexpMatchDomain);
|
||||||
favicon = favicon ? URLS.favicon(favicon[1]) : '';
|
favicon = favicon ? URLS.favicon(favicon[1]) : '';
|
||||||
}
|
}
|
||||||
if (favicon) {
|
if (!favicon) continue;
|
||||||
const img = target.children[0];
|
const img = $(':scope > img:first-child', target) ||
|
||||||
if (!img || img.localName !== 'img') {
|
target.insertAdjacentElement('afterbegin', $create('img', {loading: 'lazy'}));
|
||||||
target.insertAdjacentElement('afterbegin', document.createElement('img'))
|
if ((img.dataset.src || img.src) !== favicon) {
|
||||||
.dataset.src = favicon;
|
img.src = favicon;
|
||||||
} else if ((img.dataset.src || img.src) !== favicon) {
|
|
||||||
img.src = '';
|
|
||||||
img.dataset.src = favicon;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadFavicons();
|
|
||||||
}
|
|
||||||
|
|
||||||
function fitSelectBox(...elems) {
|
function fitSelectBox(...elems) {
|
||||||
const data = [];
|
const data = [];
|
||||||
|
@ -281,37 +302,6 @@ function highlightEditedStyle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadFavicons({all = false} = {}) {
|
|
||||||
if (!installed.firstElementChild) return;
|
|
||||||
let favicons = [];
|
|
||||||
if (all) {
|
|
||||||
favicons = $$('img[data-src]', installed);
|
|
||||||
} else {
|
|
||||||
const {left, top} = installed.firstElementChild.getBoundingClientRect();
|
|
||||||
const x = Math.max(0, left);
|
|
||||||
const y = Math.max(0, top);
|
|
||||||
const first = document.elementFromPoint(x, y);
|
|
||||||
if (!first) return requestAnimationFrame(loadFavicons.bind(null, ...arguments));
|
|
||||||
const lastOffset = first.offsetTop + window.innerHeight;
|
|
||||||
const numTargets = newUI.targets;
|
|
||||||
let entry = first && first.closest('.entry') || installed.children[0];
|
|
||||||
while (entry && entry.offsetTop <= lastOffset) {
|
|
||||||
favicons.push(...$$('img', entry).slice(0, numTargets).filter(img => img.dataset.src));
|
|
||||||
entry = entry.nextElementSibling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let i = 0;
|
|
||||||
for (const img of favicons) {
|
|
||||||
img.src = img.dataset.src;
|
|
||||||
delete img.dataset.src;
|
|
||||||
// loading too many icons at once will block the page while the new layout is recalculated
|
|
||||||
if (++i > 100) break;
|
|
||||||
}
|
|
||||||
if ($('img[data-src]', installed)) {
|
|
||||||
debounce(loadFavicons, 1, {all: true});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adding spaces so CSS can detect "bigness" of a value via amount of spaces at the beginning */
|
/** Adding spaces so CSS can detect "bigness" of a value via amount of spaces at the beginning */
|
||||||
function padLeft(val, width) {
|
function padLeft(val, width) {
|
||||||
val = `${val}`;
|
val = `${val}`;
|
||||||
|
@ -354,11 +344,11 @@ function showStyles(styles = [], matchUrlIds) {
|
||||||
filterAndAppend({container: renderBin}).then(sorter.updateStripes);
|
filterAndAppend({container: renderBin}).then(sorter.updateStripes);
|
||||||
if (index < sorted.length) {
|
if (index < sorted.length) {
|
||||||
requestAnimationFrame(renderStyles);
|
requestAnimationFrame(renderStyles);
|
||||||
if (firstRun) setTimeout(getFaviconSrc);
|
if (firstRun) getFaviconSrc();
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setTimeout(getFaviconSrc);
|
getFaviconSrc();
|
||||||
if (sessionStore.justEditedStyleId) {
|
if (sessionStore.justEditedStyleId) {
|
||||||
setTimeout(highlightEditedStyle); // delaying to avoid forced layout
|
setTimeout(highlightEditedStyle); // delaying to avoid forced layout
|
||||||
} else if ('scrollY' in (history.state || {})) {
|
} else if ('scrollY' in (history.state || {})) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user