From 82a51b7ee4d989ca45a04c217e6f6716d5cc944a Mon Sep 17 00:00:00 2001 From: KV-Tube Deployer Date: Tue, 24 Mar 2026 23:35:16 +0700 Subject: [PATCH] Fix TypeScript errors in onError handlers for image/video elements --- frontend/app/components/VideoCard.tsx | 6 ++++-- frontend/app/feed/library/page.tsx | 6 ++++-- frontend/app/feed/subscriptions/page.tsx | 6 ++++-- frontend/app/search/page.tsx | 11 +++++++---- frontend/app/watch/Comments.tsx | 5 +++-- frontend/app/watch/PlaylistPanel.tsx | 6 ++++-- frontend/app/watch/RelatedVideos.tsx | 6 ++++-- frontend/app/watch/VideoPlayer.tsx | 6 ++++-- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/frontend/app/components/VideoCard.tsx b/frontend/app/components/VideoCard.tsx index af27507..21cb76b 100644 --- a/frontend/app/components/VideoCard.tsx +++ b/frontend/app/components/VideoCard.tsx @@ -52,8 +52,10 @@ function VideoCard({ video, hideChannelAvatar }: { video: VideoData; hideChannel className="videocard-thumb" priority={false} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {video.duration && !video.is_mix && ( diff --git a/frontend/app/feed/library/page.tsx b/frontend/app/feed/library/page.tsx index 5e271b2..b477f65 100644 --- a/frontend/app/feed/library/page.tsx +++ b/frontend/app/feed/library/page.tsx @@ -150,8 +150,10 @@ export default async function LibraryPage() { className="videocard-thumb" style={{ width: '100%', height: '100%', objectFit: 'cover' }} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {video.duration && ( diff --git a/frontend/app/feed/subscriptions/page.tsx b/frontend/app/feed/subscriptions/page.tsx index 9d114c9..6a8241c 100644 --- a/frontend/app/feed/subscriptions/page.tsx +++ b/frontend/app/feed/subscriptions/page.tsx @@ -124,8 +124,10 @@ export default async function SubscriptionsPage() { alt={video.title} style={{ width: '100%', height: '100%', objectFit: 'cover' }} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {video.duration && ( diff --git a/frontend/app/search/page.tsx b/frontend/app/search/page.tsx index 15be355..b2a1014 100644 --- a/frontend/app/search/page.tsx +++ b/frontend/app/search/page.tsx @@ -88,8 +88,10 @@ async function SearchResults({ query }: { query: string }) { style={{ width: '100%', height: '100%', objectFit: 'cover', backgroundColor: '#272727' }} className="search-result-thumb" onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {v.duration && ( @@ -119,8 +121,9 @@ async function SearchResults({ query }: { query: string }) { alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/img/channels/c_ip_m_default.jpg'; // Fallback to YouTube's default channel avatar + const img = e.target as HTMLImageElement; + img.onerror = null; + img.src = 'https://i.ytimg.com/img/channels/c_ip_m_default.jpg'; // Fallback to YouTube's default channel avatar }} /> ) : firstLetter} diff --git a/frontend/app/watch/Comments.tsx b/frontend/app/watch/Comments.tsx index b0aebcb..ab04afe 100644 --- a/frontend/app/watch/Comments.tsx +++ b/frontend/app/watch/Comments.tsx @@ -122,8 +122,9 @@ export default function Comments({ videoId }: CommentsProps) { sizes="40px" style={{ objectFit: 'cover' }} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/img/channels/c_ip_m_default.jpg'; // Fallback to YouTube's default channel avatar + const img = e.target as HTMLImageElement; + img.onerror = null; + img.src = 'https://i.ytimg.com/img/channels/c_ip_m_default.jpg'; // Fallback to YouTube's default channel avatar }} /> diff --git a/frontend/app/watch/PlaylistPanel.tsx b/frontend/app/watch/PlaylistPanel.tsx index a02bb5e..7a5c32d 100644 --- a/frontend/app/watch/PlaylistPanel.tsx +++ b/frontend/app/watch/PlaylistPanel.tsx @@ -100,8 +100,10 @@ export default function PlaylistPanel({ videos, currentVideoId, listId, title }: sizes="100px" style={{ objectFit: 'cover' }} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {video.duration && ( diff --git a/frontend/app/watch/RelatedVideos.tsx b/frontend/app/watch/RelatedVideos.tsx index bef7403..866621f 100644 --- a/frontend/app/watch/RelatedVideos.tsx +++ b/frontend/app/watch/RelatedVideos.tsx @@ -54,8 +54,10 @@ export default async function RelatedVideos({ videoId, title, uploader }: { vide alt={video.title} className="related-thumb-img" onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const img = e.target as HTMLImageElement; + if (img.src !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + img.src = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} /> {video.duration && ( diff --git a/frontend/app/watch/VideoPlayer.tsx b/frontend/app/watch/VideoPlayer.tsx index de55024..4a9d651 100644 --- a/frontend/app/watch/VideoPlayer.tsx +++ b/frontend/app/watch/VideoPlayer.tsx @@ -569,8 +569,10 @@ export default function VideoPlayer({ videoId, title }: VideoPlayerProps) { preload="auto" poster={`https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg`} onError={(e) => { - e.target.onError = null; // Prevent infinite loop - e.target.poster = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; // Fallback to YouTube's default thumbnail + const video = e.target as HTMLVideoElement; + if (video.poster !== 'https://i.ytimg.com/vi/default/hqdefault.jpg') { + video.poster = 'https://i.ytimg.com/vi/default/hqdefault.jpg'; + } }} />