diff --git a/src/apps/karaoke/components/KaraokeAppComponent.tsx b/src/apps/karaoke/components/KaraokeAppComponent.tsx index 84655859a..2c68970d5 100644 --- a/src/apps/karaoke/components/KaraokeAppComponent.tsx +++ b/src/apps/karaoke/components/KaraokeAppComponent.tsx @@ -166,6 +166,7 @@ export function KaraokeAppComponent({ handleSendReaction, handlePlayTrack, handleToggleCoverFlow, + handleOpenCoverFlow, handleCoverFlowSelectTrack, handleCoverFlowPlayInPlace, handleCoverFlowRotation, @@ -241,6 +242,12 @@ export function KaraokeAppComponent({ tracks, ]); + const handleTitleCardCoverClick = useCallback(() => { + userHasInteractedRef.current = true; + registerActivity(); + handleOpenCoverFlow(); + }, [handleOpenCoverFlow, registerActivity]); + const handleFullscreenLyricsSwipeDown = useCallback(() => { if (isOffline) { showOfflineStatus(); @@ -583,6 +590,7 @@ export function KaraokeAppComponent({ koreanDisplay={koreanDisplay} japaneseFurigana={japaneseFurigana} lyricsAlignment={lyricsAlignment} + onTitleCardCoverClick={handleTitleCardCoverClick} /> diff --git a/src/apps/karaoke/components/KaraokeLyricsPlayback.tsx b/src/apps/karaoke/components/KaraokeLyricsPlayback.tsx index 29444e887..4286df5c0 100644 --- a/src/apps/karaoke/components/KaraokeLyricsPlayback.tsx +++ b/src/apps/karaoke/components/KaraokeLyricsPlayback.tsx @@ -336,6 +336,8 @@ function KaraokeTitleCard({ variant, coverUrl, bottomPaddingClass = "pb-12", + onCoverClick, + coverArtAriaLabel, }: { title: string; artist?: string; @@ -344,6 +346,9 @@ function KaraokeTitleCard({ variant: "window" | "fullscreen"; coverUrl?: string | null; bottomPaddingClass?: string; + /** When set, album art opens Cover Flow (parent handles empty library). */ + onCoverClick?: () => void; + coverArtAriaLabel?: string; }) { const styleCategory = getTitleCardStyleCategory(fontClassName); const palette = useCoverPalette(styleCategory === "glow-gold" ? (coverUrl ?? null) : null); @@ -454,14 +459,34 @@ function KaraokeTitleCard({ > {coverUrl && (
-
- -
+ {onCoverClick ? ( + + ) : ( +
+ +
+ )}
void; } export function KaraokeWindowLyricsOverlay({ @@ -547,6 +573,7 @@ export function KaraokeWindowLyricsOverlay({ koreanDisplay, japaneseFurigana, lyricsAlignment, + onTitleCardCoverClick, }: WindowLyricsProps) { const { lyricsControls, @@ -602,6 +629,8 @@ export function KaraokeWindowLyricsOverlay({ variant="window" coverUrl={coverUrl} bottomPaddingClass={bottomPadding} + onCoverClick={onTitleCardCoverClick} + coverArtAriaLabel={t("apps.ipod.menu.coverFlow")} /> )} @@ -666,6 +695,7 @@ interface FullscreenLyricsProps { /** When set (e.g. fullscreen), replaces default next/previous swipe behavior */ onSwipeUp?: () => void; onSwipeDown?: () => void; + onTitleCardCoverClick?: () => void; } export function KaraokeFullscreenLyricsOverlay({ @@ -687,6 +717,7 @@ export function KaraokeFullscreenLyricsOverlay({ lyricsAlignment, onSwipeUp: onSwipeUpOverride, onSwipeDown: onSwipeDownOverride, + onTitleCardCoverClick, }: FullscreenLyricsProps) { const { lyricsControls, @@ -741,6 +772,8 @@ export function KaraokeFullscreenLyricsOverlay({ variant="fullscreen" coverUrl={coverUrl} bottomPaddingClass={bottomPadding} + onCoverClick={onTitleCardCoverClick} + coverArtAriaLabel={t("apps.ipod.menu.coverFlow")} /> )} diff --git a/src/apps/karaoke/hooks/useKaraokeLogic.ts b/src/apps/karaoke/hooks/useKaraokeLogic.ts index b46ac8b0b..8d7d8fffe 100644 --- a/src/apps/karaoke/hooks/useKaraokeLogic.ts +++ b/src/apps/karaoke/hooks/useKaraokeLogic.ts @@ -1287,6 +1287,13 @@ export function useKaraokeLogic({ } }, [isCoverFlowOpen, tracks.length]); + /** Open Cover Flow without toggling closed (e.g. title card album art). */ + const handleOpenCoverFlow = useCallback(() => { + if (tracks.length > 0) { + setIsCoverFlowOpen(true); + } + }, [tracks.length]); + // CoverFlow track selection handler const handleCoverFlowSelectTrack = useCallback( (index: number) => { @@ -1682,6 +1689,7 @@ export function useKaraokeLogic({ handleAddUrl, handlePlayTrack, handleToggleCoverFlow, + handleOpenCoverFlow, handleCoverFlowSelectTrack, handleCoverFlowPlayInPlace, handleCoverFlowRotation,