bugfixes, and logging cleanup

This commit is contained in:
Stefan Hardegger
2025-09-21 14:51:21 +02:00
parent 58bb7f8229
commit 0101c0ca2c
11 changed files with 271 additions and 120 deletions

View File

@@ -11,6 +11,7 @@ import StoryRating from '../../../components/stories/StoryRating';
import TagDisplay from '../../../components/tags/TagDisplay';
import TableOfContents from '../../../components/stories/TableOfContents';
import { sanitizeHtml, preloadSanitizationConfig } from '../../../lib/sanitization';
import { debug } from '../../../lib/debug';
// Memoized content component that only re-renders when content changes
const StoryContent = memo(({
@@ -20,13 +21,50 @@ const StoryContent = memo(({
content: string;
contentRef: React.RefObject<HTMLDivElement>;
}) => {
console.log('🔄 StoryContent component rendering with content length:', content.length);
const renderTime = Date.now();
debug.log('🔄 StoryContent component rendering at', renderTime, 'with content length:', content.length, 'hash:', content.slice(0, 50) + '...');
// Add observer to track image loading events
useEffect(() => {
if (!contentRef.current) return;
const images = contentRef.current.querySelectorAll('img');
debug.log('📸 Found', images.length, 'images in content');
const handleImageLoad = (e: Event) => {
const img = e.target as HTMLImageElement;
debug.log('🖼️ Image loaded:', img.src);
};
const handleImageError = (e: Event) => {
const img = e.target as HTMLImageElement;
debug.log('❌ Image error:', img.src);
};
images.forEach(img => {
img.addEventListener('load', handleImageLoad);
img.addEventListener('error', handleImageError);
debug.log('👀 Monitoring image:', img.src);
});
return () => {
images.forEach(img => {
img.removeEventListener('load', handleImageLoad);
img.removeEventListener('error', handleImageError);
});
};
}, [content]);
return (
<div
ref={contentRef}
className="reading-content"
dangerouslySetInnerHTML={{ __html: content }}
style={{
// Prevent layout shifts that might cause image reloads
minHeight: '100vh',
contain: 'layout style'
}}
/>
);
});
@@ -112,14 +150,14 @@ export default function StoryReadingPage() {
// Debounced function to save reading position
const saveReadingPosition = useCallback(async (position: number) => {
if (!story || position === story.readingPosition) {
console.log('Skipping save - no story or position unchanged:', { story: !!story, position, current: story?.readingPosition });
debug.log('Skipping save - no story or position unchanged:', { story: !!story, position, current: story?.readingPosition });
return;
}
console.log('Saving reading position:', position, 'for story:', story.id);
debug.log('Saving reading position:', position, 'for story:', story.id);
try {
const updatedStory = await storyApi.updateReadingProgress(story.id, position);
console.log('Reading position saved successfully, updated story:', updatedStory.readingPosition);
debug.log('Reading position saved successfully, updated story:', updatedStory.readingPosition);
setStory(prev => prev ? { ...prev, readingPosition: position, lastReadAt: updatedStory.lastReadAt } : null);
} catch (error) {
console.error('Failed to save reading position:', error);
@@ -200,12 +238,12 @@ export default function StoryReadingPage() {
if (story && sanitizedContent && !hasScrolledToPosition) {
// Use a small delay to ensure content is rendered
const timeout = setTimeout(() => {
console.log('Initializing reading position tracking, saved position:', story.readingPosition);
debug.log('Initializing reading position tracking, saved position:', story.readingPosition);
// Check if there's a hash in the URL (for TOC navigation)
const hash = window.location.hash.substring(1);
if (hash && hash.startsWith('heading-')) {
console.log('Auto-scrolling to heading from URL hash:', hash);
debug.log('Auto-scrolling to heading from URL hash:', hash);
const element = document.getElementById(hash);
if (element) {
element.scrollIntoView({
@@ -219,13 +257,13 @@ export default function StoryReadingPage() {
// Otherwise, use saved reading position
if (story.readingPosition && story.readingPosition > 0) {
console.log('Auto-scrolling to saved position:', story.readingPosition);
debug.log('Auto-scrolling to saved position:', story.readingPosition);
const initialPercentage = calculateReadingPercentage(story.readingPosition);
setReadingPercentage(initialPercentage);
scrollToCharacterPosition(story.readingPosition);
} else {
// Even if there's no saved position, mark as ready for tracking
console.log('No saved position, starting fresh tracking');
debug.log('No saved position, starting fresh tracking');
setReadingPercentage(0);
setHasScrolledToPosition(true);
}
@@ -238,8 +276,14 @@ export default function StoryReadingPage() {
// Track reading progress and save position
useEffect(() => {
let ticking = false;
let scrollEventCount = 0;
const handleScroll = () => {
scrollEventCount++;
if (scrollEventCount % 10 === 0) {
debug.log('📜 Scroll event #', scrollEventCount, 'at', Date.now());
}
if (!ticking) {
requestAnimationFrame(() => {
const article = document.querySelector('[data-reading-content]') as HTMLElement;
@@ -278,7 +322,7 @@ export default function StoryReadingPage() {
// Trigger end detection if user is near bottom AND (has high progress OR story content is fully visible)
if (nearBottom && (highProgress || storyContentFullyVisible) && !hasReachedEnd && hasScrolledToPosition) {
console.log('End of story detected:', { nearBottom, highProgress, storyContentFullyVisible, distanceFromBottom, progress });
debug.log('End of story detected:', { nearBottom, highProgress, storyContentFullyVisible, distanceFromBottom, progress });
setHasReachedEnd(true);
setShowEndOfStoryPopup(true);
}
@@ -287,11 +331,11 @@ export default function StoryReadingPage() {
if (hasScrolledToPosition) { // Only save after initial auto-scroll
const characterPosition = getCharacterPositionFromScroll();
const percentage = calculateReadingPercentage(characterPosition);
console.log('Scroll detected, character position:', characterPosition, 'percentage:', percentage);
debug.log('Scroll detected, character position:', characterPosition, 'percentage:', percentage);
setReadingPercentage(percentage);
debouncedSavePosition(characterPosition);
} else {
console.log('Scroll detected but not ready for tracking yet');
debug.log('Scroll detected but not ready for tracking yet');
}
}
ticking = false;