Fix mobile infinite scroll on object list and ghost preview on fast object swap

This commit is contained in:
2026-03-23 11:55:46 +08:00
parent 5e32cef792
commit eff3e378f3
2 changed files with 18 additions and 3 deletions

View File

@@ -2655,7 +2655,7 @@ pre code {
} }
.objects-table-container { .objects-table-container {
max-height: none; max-height: 60vh;
} }
.preview-card { .preview-card {

View File

@@ -98,6 +98,7 @@
const previewMetadata = document.getElementById('preview-metadata'); const previewMetadata = document.getElementById('preview-metadata');
const previewMetadataList = document.getElementById('preview-metadata-list'); const previewMetadataList = document.getElementById('preview-metadata-list');
const previewPlaceholder = document.getElementById('preview-placeholder'); const previewPlaceholder = document.getElementById('preview-placeholder');
const previewPlaceholderDefault = previewPlaceholder ? previewPlaceholder.innerHTML : '';
const previewImage = document.getElementById('preview-image'); const previewImage = document.getElementById('preview-image');
const previewVideo = document.getElementById('preview-video'); const previewVideo = document.getElementById('preview-video');
const previewAudio = document.getElementById('preview-audio'); const previewAudio = document.getElementById('preview-audio');
@@ -1957,6 +1958,10 @@
[previewImage, previewVideo, previewAudio, previewIframe].forEach((el) => { [previewImage, previewVideo, previewAudio, previewIframe].forEach((el) => {
if (!el) return; if (!el) return;
el.classList.add('d-none'); el.classList.add('d-none');
if (el.tagName === 'IMG') {
el.removeAttribute('src');
el.onload = null;
}
if (el.tagName === 'VIDEO' || el.tagName === 'AUDIO') { if (el.tagName === 'VIDEO' || el.tagName === 'AUDIO') {
el.pause(); el.pause();
el.removeAttribute('src'); el.removeAttribute('src');
@@ -1969,6 +1974,7 @@
previewText.classList.add('d-none'); previewText.classList.add('d-none');
previewText.textContent = ''; previewText.textContent = '';
} }
previewPlaceholder.innerHTML = previewPlaceholderDefault;
previewPlaceholder.classList.remove('d-none'); previewPlaceholder.classList.remove('d-none');
}; };
@@ -2016,9 +2022,18 @@
const previewUrl = row.dataset.previewUrl; const previewUrl = row.dataset.previewUrl;
const lower = row.dataset.key.toLowerCase(); const lower = row.dataset.key.toLowerCase();
if (previewUrl && lower.match(/\.(png|jpg|jpeg|gif|webp|svg|ico|bmp)$/)) { if (previewUrl && lower.match(/\.(png|jpg|jpeg|gif|webp|svg|ico|bmp)$/)) {
previewImage.src = previewUrl; previewPlaceholder.innerHTML = '<div class="spinner-border spinner-border-sm text-secondary" role="status"></div><div class="small mt-2">Loading preview\u2026</div>';
const currentRow = row;
previewImage.onload = () => {
if (activeRow !== currentRow) return;
previewImage.classList.remove('d-none'); previewImage.classList.remove('d-none');
previewPlaceholder.classList.add('d-none'); previewPlaceholder.classList.add('d-none');
};
previewImage.onerror = () => {
if (activeRow !== currentRow) return;
previewPlaceholder.innerHTML = '<div class="small text-muted">Failed to load preview</div>';
};
previewImage.src = previewUrl;
} else if (previewUrl && lower.match(/\.(mp4|webm|ogv|mov|avi|mkv)$/)) { } else if (previewUrl && lower.match(/\.(mp4|webm|ogv|mov|avi|mkv)$/)) {
previewVideo.src = previewUrl; previewVideo.src = previewUrl;
previewVideo.classList.remove('d-none'); previewVideo.classList.remove('d-none');