From 808da507f667d05a32a08e279d880bf7ab4f020b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Apr 2026 23:34:57 +0000 Subject: [PATCH] Use visible YouTube player for song preview (ToS compliance) Preview now uses YouTube IFrame API with a visible 240x135 player in the top-left corner of the song select screen, matching the game page layout. Falls back to local audio for songs without YouTube config. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/features/song-select/SongSelectScreen.css | 21 +++++++ src/features/song-select/SongSelectScreen.tsx | 7 ++- src/features/song-select/useSongPreview.ts | 56 ++++++------------- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/features/song-select/SongSelectScreen.css b/src/features/song-select/SongSelectScreen.css index e7798eb..ea6d80d 100644 --- a/src/features/song-select/SongSelectScreen.css +++ b/src/features/song-select/SongSelectScreen.css @@ -56,6 +56,27 @@ opacity: 0.35; } +.song-select-screen__yt-preview { + position: fixed; + top: 12px; + left: 12px; + width: 240px; + height: 135px; + z-index: 10; + border-radius: 10px; + overflow: hidden; + border: 2px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6); + pointer-events: none; +} + +.song-select-screen__yt-preview iframe { + display: block; + width: 100%; + height: 100%; + border: 0; +} + .song-select-screen__content { position: relative; z-index: 2; diff --git a/src/features/song-select/SongSelectScreen.tsx b/src/features/song-select/SongSelectScreen.tsx index 8893bc2..f0cd199 100644 --- a/src/features/song-select/SongSelectScreen.tsx +++ b/src/features/song-select/SongSelectScreen.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from 'react' +import { useMemo, useRef, useState } from 'react' import type { CSSProperties } from 'react' import { useNavigate } from 'react-router-dom' import { useGameInput } from '../../input/useGameInput' @@ -26,8 +26,9 @@ export function SongSelectScreen() { const resetStats = useGameStatsStore((state) => state.resetStats) const [currentIndex, setCurrentIndex] = useState(0) const activeSong = SONGS[currentIndex] + const ytPreviewRef = useRef(null) - useSongPreview(activeSong) + useSongPreview(activeSong, ytPreviewRef.current) const handleConfirm = () => { setCurrentSong(activeSong) @@ -74,6 +75,8 @@ export function SongSelectScreen() { difficulty={activeSong.difficulty} /> +
+