home improvements

This commit is contained in:
ld3zian 2025-01-31 20:59:17 -07:00
parent f8ceba0d0d
commit f20097e45c
3 changed files with 57 additions and 11 deletions

View file

@ -31,6 +31,8 @@ const isNSFW = comic.md_comics.content_rating === 'erotica';
alt={comic.md_comics.title}
inferSize={true}
class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110"
loading="lazy"
decoding="async"
/>
) : (
<img
@ -52,7 +54,10 @@ const isNSFW = comic.md_comics.content_rating === 'erotica';
<div class="p-3 sm:p-4 md:p-5 flex-grow flex flex-col bg-secondary relative rounded-b-xl">
<div class="absolute -top-6 sm:-top-8 left-2 right-2 sm:left-3 sm:right-3 bg-secondary/95 backdrop-blur-[12px] p-2 sm:p-3 rounded-lg shadow-lg border border-hover/30">
<h3 id={`comic-title-${comic.id}`} class="text-base sm:text-lg font-bold line-clamp-1 text-center text-primary drop-shadow-[0_1px_1px_rgba(0,0,0,0.5)]">
<h3 id={`comic-title-${comic.id}`}
class="text-base sm:text-lg font-bold line-clamp-1 text-center text-primary drop-shadow-[0_1px_1px_rgba(0,0,0,0.5)]"
aria-label={comic.md_comics.title}
>
{comic.md_comics.title}
</h3>
</div>
@ -219,22 +224,37 @@ const isNSFW = comic.md_comics.content_rating === 'erotica';
timerSpan.textContent = timeString;
}
// Add intersection observer for lazy loading
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const timer = entry.target.querySelector('.countdown-timer');
if (timer) updateTimer(timer);
}
});
});
// Update countdown timer initialization
countdownTimers.forEach(timer => {
observer.observe(timer);
updateTimer(timer);
// Update every second
setInterval(() => updateTimer(timer), 1000);
setInterval(() => {
if (timer.isConnected) updateTimer(timer);
}, 1000);
});
});
function filterComics() {
const excludedGenres = new Set(JSON.parse(localStorage.getItem('excluded-genres') || '[]'));
// Use requestAnimationFrame for smoother updates
requestAnimationFrame(() => {
document.querySelectorAll('[data-genres]').forEach(card => {
const cardGenres = JSON.parse((card as HTMLElement).dataset.genres || '[]');
const shouldHide = cardGenres.some((genreId: number) => excludedGenres.has(genreId));
card.classList.toggle('hidden', shouldHide);
});
});
}
// Listen for genre updates

View file

@ -125,8 +125,15 @@ const languages = [
const promises = [...slugs].map(async (slug) => {
try {
// Use our API endpoint instead of direct ComicK API call
const response = await fetch(`/api/comic/${encodeURIComponent(slug)}`);
// Add timeout for comic info fetch
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
const response = await fetch(`/api/comic/${encodeURIComponent(slug)}`, {
signal: controller.signal
});
clearTimeout(timeoutId);
if (!response.ok) throw new Error('Comic not found');
const data = await response.json();
@ -333,6 +340,17 @@ const languages = [
if (slugString) {
try {
// Add loading state
generateRSSLink!.innerHTML = `
<span class="flex items-center gap-2">
<svg class="w-5 h-5 animate-spin" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" stroke-linecap="round"/>
</svg>
Generating...
</span>
`;
generateRSSLink!.onclick = null;
const response = await fetch('/api/create-feed', {
method: 'POST',
headers: {
@ -348,9 +366,16 @@ const languages = [
const { feedId } = await response.json();
generateRSSLink!.href = `/rss/${feedId}.xml`;
generateRSSLink!.onclick = null;
} catch (error) {
console.error('Failed to generate feed:', error);
generateRSSLink!.innerHTML = `
<span class="flex items-center gap-2">
<svg class="w-5 h-5 animate-spin" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none" stroke-linecap="round"/>
</svg>
Failed to generate feed
</span>
`;
}
} else {
generateRSSLink!.href = '#';

View file

@ -276,5 +276,6 @@ const announcement = {
<style define:vars={{ bgUrl: background.url }}>
body::before {
background-image: var(--bg-url);
transition: background-image 0.5s ease-in-out;
}
</style>