detect all images and add a fade in animation on image loads

This commit is contained in:
Pas 2025-11-07 23:47:30 -07:00
parent ba7c079b75
commit bf1bb2775b
3 changed files with 73 additions and 0 deletions

View file

@ -427,3 +427,19 @@ input[type="range"].styled-slider.slider-progress::-ms-fill-lower {
.google-cast-button:not(.casting) google-cast-launcher {
@apply brightness-[500];
}
/* Image fade-in on load */
img:not([src=""]) {
opacity: 0;
transition: opacity 0.8s ease-in-out;
}
/* Fade in when image has loaded class */
img.loaded {
opacity: 1;
}
/* For images that are already cached/loaded, show them immediately */
img[complete]:not([src=""]) {
opacity: 1;
}

View file

@ -37,10 +37,12 @@ import {
isExtensionActiveCached,
} from "./backend/extension/messaging";
import { initializeChromecast } from "./setup/chromecast";
import { initializeImageFadeIn } from "./setup/imageFadeIn";
import { initializeOldStores } from "./stores/__old/migrations";
// initialize
initializeChromecast();
initializeImageFadeIn();
function LoadingScreen(props: { type: "user" | "lazy" }) {
const mapping = {

55
src/setup/imageFadeIn.ts Normal file
View file

@ -0,0 +1,55 @@
/**
* Global image fade-in handler
* Automatically adds 'loaded' class to images when they finish loading
*/
export function initializeImageFadeIn() {
// Handle images that are already loaded (cached)
const handleExistingImages = () => {
const images = document.querySelectorAll("img:not(.loaded)");
images.forEach((img) => {
const htmlImg = img as HTMLImageElement;
if (htmlImg.complete && htmlImg.naturalHeight !== 0) {
htmlImg.classList.add("loaded");
}
});
};
// Handle images that load after DOM is ready
const handleImageLoad = (e: Event) => {
const img = e.target as HTMLImageElement;
if (img.tagName === "IMG") {
img.classList.add("loaded");
}
};
// Use event delegation for all images (including dynamically added ones)
document.addEventListener("load", handleImageLoad, true);
// Handle existing images on initialization
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", handleExistingImages);
} else {
handleExistingImages();
}
// Also check periodically for images that might have loaded
// This handles edge cases where the load event might not fire
const checkInterval = setInterval(() => {
const images = document.querySelectorAll("img:not(.loaded)");
if (images.length === 0) {
clearInterval(checkInterval);
return;
}
images.forEach((img) => {
const htmlImg = img as HTMLImageElement;
if (htmlImg.complete && htmlImg.naturalHeight !== 0) {
htmlImg.classList.add("loaded");
}
});
}, 100);
// Clean up interval after 10 seconds to avoid memory leaks
setTimeout(() => {
clearInterval(checkInterval);
}, 10000);
}