Public: defer category image fetch and unblock card navigation
Avoid navigation stalls on cold loads by delaying thumbnail requests until cards are near viewport. Stop in-flight page downloads on card click so opening a photo page is immediate even while list images are still loading.
This commit is contained in:
parent
92e606a87e
commit
0eefcf6b04
49
index.php
49
index.php
|
|
@ -239,7 +239,7 @@ function outputWatermarked(string $path, string $mime): never
|
||||||
<div class="cards">
|
<div class="cards">
|
||||||
<?php foreach($photos as $p): ?>
|
<?php foreach($photos as $p): ?>
|
||||||
<a class="card" href="?photo_id=<?= (int)$p['id'] ?>§ion_id=<?= (int)$activeSectionId ?><?= $viewerToken!=='' ? '&viewer=' . urlencode($viewerToken) : '' ?>" style="text-decoration:none;color:inherit;position:relative">
|
<a class="card" href="?photo_id=<?= (int)$p['id'] ?>§ion_id=<?= (int)$activeSectionId ?><?= $viewerToken!=='' ? '&viewer=' . urlencode($viewerToken) : '' ?>" style="text-decoration:none;color:inherit;position:relative">
|
||||||
<?php if (!empty($p['before_file_id'])): ?><div class="img-box thumb-img-box is-loading"><img class="js-public-image" src="?action=image&file_id=<?= (int)$p['before_file_id'] ?>" alt="" loading="lazy" decoding="async" fetchpriority="low"></div><?php endif; ?>
|
<?php if (!empty($p['before_file_id'])): ?><div class="img-box thumb-img-box is-loading"><img class="js-public-image js-card-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==" data-src="?action=image&file_id=<?= (int)$p['before_file_id'] ?>" alt="" loading="lazy" decoding="async" fetchpriority="low"></div><?php endif; ?>
|
||||||
<?php if (!empty($p['after_file_id'])): ?><span title="Есть обработанная версия" style="position:absolute;top:8px;right:8px;background:rgba(31,111,235,.92);color:#fff;font-size:11px;line-height:1;padding:6px 7px;border-radius:999px">AI</span><?php endif; ?>
|
<?php if (!empty($p['after_file_id'])): ?><span title="Есть обработанная версия" style="position:absolute;top:8px;right:8px;background:rgba(31,111,235,.92);color:#fff;font-size:11px;line-height:1;padding:6px 7px;border-radius:999px">AI</span><?php endif; ?>
|
||||||
<div class="cap"><strong><?= h((string)$p['code_name']) ?></strong><br><span class="muted"><?= h((string)($p['description'] ?? '')) ?></span></div>
|
<div class="cap"><strong><?= h((string)$p['code_name']) ?></strong><br><span class="muted"><?= h((string)($p['description'] ?? '')) ?></span></div>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -257,6 +257,34 @@ function outputWatermarked(string $path, string $mime): never
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
(() => {
|
||||||
|
const loadCardImage = (img) => {
|
||||||
|
const src = img.dataset.src;
|
||||||
|
if (!src) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.src = src;
|
||||||
|
img.removeAttribute('data-src');
|
||||||
|
};
|
||||||
|
|
||||||
|
const deferred = document.querySelectorAll('.js-card-image[data-src]');
|
||||||
|
if ('IntersectionObserver' in window) {
|
||||||
|
const io = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (!entry.isIntersecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCardImage(entry.target);
|
||||||
|
io.unobserve(entry.target);
|
||||||
|
});
|
||||||
|
}, { rootMargin: '240px 0px' });
|
||||||
|
|
||||||
|
deferred.forEach((img) => io.observe(img));
|
||||||
|
} else {
|
||||||
|
deferred.forEach((img) => loadCardImage(img));
|
||||||
|
}
|
||||||
|
|
||||||
document.querySelectorAll('img').forEach((img) => {
|
document.querySelectorAll('img').forEach((img) => {
|
||||||
img.addEventListener('contextmenu', (e) => e.preventDefault());
|
img.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
img.addEventListener('dragstart', (e) => e.preventDefault());
|
img.addEventListener('dragstart', (e) => e.preventDefault());
|
||||||
|
|
@ -275,10 +303,27 @@ function outputWatermarked(string $path, string $mime): never
|
||||||
img.addEventListener('load', clearLoading, { once: true });
|
img.addEventListener('load', clearLoading, { once: true });
|
||||||
img.addEventListener('error', clearLoading, { once: true });
|
img.addEventListener('error', clearLoading, { once: true });
|
||||||
|
|
||||||
if (img.complete) {
|
if (img.complete && !img.dataset.src) {
|
||||||
clearLoading();
|
clearLoading();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('a.card').forEach((link) => {
|
||||||
|
link.addEventListener('click', (e) => {
|
||||||
|
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const href = link.getAttribute('href');
|
||||||
|
if (!href) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
window.stop();
|
||||||
|
window.location.assign(href);
|
||||||
|
});
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user