Fix image loading
This commit is contained in:
@@ -8,6 +8,27 @@ import { storyApi, getImageUrl } from '../../lib/api';
|
|||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import TagDisplay from '../tags/TagDisplay';
|
import TagDisplay from '../tags/TagDisplay';
|
||||||
|
|
||||||
|
// Detects systemic image load failures (e.g. wrong library ID) and reloads the page.
|
||||||
|
// Guards against infinite loops: max 2 auto-reloads per session.
|
||||||
|
const imageErrorTracker = {
|
||||||
|
errors: [] as number[],
|
||||||
|
reload() {
|
||||||
|
const count = parseInt(sessionStorage.getItem('storycove-reload-count') || '0');
|
||||||
|
if (count < 2) {
|
||||||
|
sessionStorage.setItem('storycove-reload-count', String(count + 1));
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
report() {
|
||||||
|
const now = Date.now();
|
||||||
|
this.errors = this.errors.filter(t => now - t < 3000);
|
||||||
|
this.errors.push(now);
|
||||||
|
if (this.errors.length >= 3) {
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
interface StoryCardProps {
|
interface StoryCardProps {
|
||||||
story: Story;
|
story: Story;
|
||||||
viewMode: 'grid' | 'list';
|
viewMode: 'grid' | 'list';
|
||||||
@@ -91,6 +112,7 @@ export default function StoryCard({
|
|||||||
height={80}
|
height={80}
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
unoptimized
|
unoptimized
|
||||||
|
onError={() => imageErrorTracker.report()}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full h-full flex items-center justify-center theme-text text-xs">
|
<div className="w-full h-full flex items-center justify-center theme-text text-xs">
|
||||||
@@ -209,6 +231,7 @@ export default function StoryCard({
|
|||||||
height={400}
|
height={400}
|
||||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
|
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200"
|
||||||
unoptimized
|
unoptimized
|
||||||
|
onError={() => imageErrorTracker.report()}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full h-full flex items-center justify-center theme-text text-6xl">
|
<div className="w-full h-full flex items-center justify-center theme-text text-6xl">
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|||||||
// If authenticated, also load current library for image URLs
|
// If authenticated, also load current library for image URLs
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/libraries/current');
|
const token = localStorage.getItem('auth-token');
|
||||||
|
const response = await fetch('/api/libraries/current', {
|
||||||
|
headers: token ? { 'Authorization': `Bearer ${token}` } : {}
|
||||||
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const library = await response.json();
|
const library = await response.json();
|
||||||
setCurrentLibraryId(library.id);
|
setCurrentLibraryId(library.id);
|
||||||
@@ -75,7 +78,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|||||||
|
|
||||||
// Load current library after successful login
|
// Load current library after successful login
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/libraries/current');
|
const token = localStorage.getItem('auth-token');
|
||||||
|
const response = await fetch('/api/libraries/current', {
|
||||||
|
headers: token ? { 'Authorization': `Bearer ${token}` } : {}
|
||||||
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const library = await response.json();
|
const library = await response.json();
|
||||||
setCurrentLibraryId(library.id);
|
setCurrentLibraryId(library.id);
|
||||||
|
|||||||
Reference in New Issue
Block a user