From 4d84014f7c69e3a8074f47f2fd7688af90feeb01 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Thu, 17 Apr 2025 18:33:33 -0700 Subject: frontend: add image gallery and MUSIC DIVER --- site/src/components/NewsFeed.tsx | 176 +++++++++++++++++++++++++-------------- site/src/components/TitleBar.tsx | 6 ++ site/src/utils.ts | 1 + 3 files changed, 120 insertions(+), 63 deletions(-) (limited to 'site/src') diff --git a/site/src/components/NewsFeed.tsx b/site/src/components/NewsFeed.tsx index 3057d61..ec682be 100644 --- a/site/src/components/NewsFeed.tsx +++ b/site/src/components/NewsFeed.tsx @@ -24,15 +24,32 @@ interface NewsFeedProps { export const NewsFeed: React.FC = ({ newsItems }) => { // Track which items are showing English content const [showEnglish, setShowEnglish] = useState>({}); + // Track which items are expanded beyond the preview + const [expanded, setExpanded] = useState>({}); + // Track the current image index for each news item + const [currentImageIndex, setCurrentImageIndex] = useState>({}); + // Track loading state for images + const [loadingImages, setLoadingImages] = useState>({}); - // Toggle language for a specific news item const toggleLanguage = (itemId: string) => { - setShowEnglish(prev => ({ - ...prev, - [itemId]: !prev[itemId] - })); + setShowEnglish((prev) => ({ ...prev, [itemId]: !prev[itemId] })); }; + const toggleExpand = (itemId: string) => { + setExpanded((prev) => ({ ...prev, [itemId]: !prev[itemId] })); + }; + + const changeImage = (itemId: string, index: number) => { + setCurrentImageIndex((prev) => ({ ...prev, [itemId]: index })); + setLoadingImages((prev) => ({ ...prev, [itemId]: true })); // Set loading state for the image + }; + + const handleImageLoad = (itemId: string) => { + setLoadingImages((prev) => ({ ...prev, [itemId]: false })); // Clear loading state when image loads + }; + + const PREVIEW_CHAR_LIMIT = 600; + return (
{newsItems.map((news) => { @@ -42,14 +59,19 @@ export const NewsFeed: React.FC = ({ newsItems }) => { day: "2-digit", }); - const gameId = news.identifier; const newsId = `${news.identifier}-${news.timestamp}-${news.content.substring(0, 20)}`; - const isEnglish = showEnglish[newsId] || false; + const isEnglish = !!showEnglish[newsId]; const hasTranslation = news.en_headline || news.en_content; - // Choose content based on language selection const displayHeadline = isEnglish && news.en_headline ? news.en_headline : news.headline; - const displayContent = isEnglish && news.en_content ? news.en_content : news.content; + const displayContent = isEnglish && news.en_content ? news.en_content! : news.content; + + // Read‑more logic + const isLong = displayContent.length > PREVIEW_CHAR_LIMIT; + const isExpanded = !!expanded[newsId]; + const contentToShow = isLong && !isExpanded + ? displayContent.slice(0, PREVIEW_CHAR_LIMIT) + "…" + : displayContent; return (
= ({ newsItems }) => { {/* Header (Game Icon + Info) */}
- {/* Game Icon */}
- {gameId.substring(0, 1)} + {news.identifier.charAt(0)}
-
{getGameTitle(news.identifier)} - - {formattedDate} - - {/* Display News Type */} + {formattedDate} {news.type && ( - - {news.type} - + {news.type} )}
- - {/* Language Toggle Button */} {hasTranslation && ( + )}
- {/* Post Image(s) */} + {/* Images */}
- {news.images.map((img, i) => ( - img.link ? ( - - news visual - - ) : ( -
- news visual -
- ) - ))} + {news.images.length > 0 && ( + <> + {/* Display only the current image */} + {(() => { + const currentIdx = currentImageIndex[newsId] || 0; + const img = news.images[currentIdx]; + + return ( +
+ {loadingImages[newsId] && ( +
+
+
+ )} + news visual handleImageLoad(newsId)} + /> +
+ ); + })()} + + {/* Image selector buttons (only shown if there are multiple images) */} + {news.images.length > 1 && ( +
+ {news.images.map((_, idx) => ( + + ))} +
+ )} + + )}
- {/* Footer with Read More Link */} + {/* Footer */} {news.url && (