Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/apps/karaoke/components/KaraokeAppComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export function KaraokeAppComponent({
handleSendReaction,
handlePlayTrack,
handleToggleCoverFlow,
handleOpenCoverFlow,
handleCoverFlowSelectTrack,
handleCoverFlowPlayInPlace,
handleCoverFlowRotation,
Expand Down Expand Up @@ -241,6 +242,12 @@ export function KaraokeAppComponent({
tracks,
]);

const handleTitleCardCoverClick = useCallback(() => {
userHasInteractedRef.current = true;
registerActivity();
handleOpenCoverFlow();
}, [handleOpenCoverFlow, registerActivity]);

const handleFullscreenLyricsSwipeDown = useCallback(() => {
if (isOffline) {
showOfflineStatus();
Expand Down Expand Up @@ -583,6 +590,7 @@ export function KaraokeAppComponent({
koreanDisplay={koreanDisplay}
japaneseFurigana={japaneseFurigana}
lyricsAlignment={lyricsAlignment}
onTitleCardCoverClick={handleTitleCardCoverClick}
/>
<KaraokeLyricsActivityIndicator />
<KaraokeSyncModeWindowPanel
Expand Down Expand Up @@ -1013,6 +1021,7 @@ export function KaraokeAppComponent({
lyricsAlignment={lyricsAlignment}
onSwipeUp={handleFullscreenLyricsSwipeUp}
onSwipeDown={handleFullscreenLyricsSwipeDown}
onTitleCardCoverClick={handleTitleCardCoverClick}
/>
</div>
</div>
Expand Down
49 changes: 41 additions & 8 deletions src/apps/karaoke/components/KaraokeLyricsPlayback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ function KaraokeTitleCard({
variant,
coverUrl,
bottomPaddingClass = "pb-12",
onCoverClick,
coverArtAriaLabel,
}: {
title: string;
artist?: string;
Expand All @@ -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);
Expand Down Expand Up @@ -454,14 +459,34 @@ function KaraokeTitleCard({
>
{coverUrl && (
<div className="relative shrink-0" style={coverImageStyle}>
<div className="absolute inset-0 overflow-hidden" style={coverSleeveStyle}>
<img
src={coverUrl}
alt=""
className="w-full h-full object-cover"
draggable={false}
/>
</div>
{onCoverClick ? (
<button
type="button"
className="absolute inset-0 z-[1] overflow-hidden cursor-pointer p-0 border-0 bg-transparent appearance-none text-left rounded-[1%] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/80 pointer-events-auto"
style={coverSleeveStyle}
aria-label={coverArtAriaLabel}
onClick={(e) => {
e.stopPropagation();
onCoverClick();
}}
>
<img
src={coverUrl}
alt=""
className="w-full h-full object-cover pointer-events-none"
draggable={false}
/>
</button>
) : (
<div className="absolute inset-0 overflow-hidden" style={coverSleeveStyle}>
<img
src={coverUrl}
alt=""
className="w-full h-full object-cover"
draggable={false}
/>
</div>
)}
<div
className="absolute top-full left-0 w-full pointer-events-none"
style={{ height: "50%" }}
Expand Down Expand Up @@ -525,6 +550,7 @@ interface WindowLyricsProps {
koreanDisplay: KoreanDisplay;
japaneseFurigana: JapaneseFurigana;
lyricsAlignment: LyricsAlignment;
onTitleCardCoverClick?: () => void;
}

export function KaraokeWindowLyricsOverlay({
Expand All @@ -547,6 +573,7 @@ export function KaraokeWindowLyricsOverlay({
koreanDisplay,
japaneseFurigana,
lyricsAlignment,
onTitleCardCoverClick,
}: WindowLyricsProps) {
const {
lyricsControls,
Expand Down Expand Up @@ -602,6 +629,8 @@ export function KaraokeWindowLyricsOverlay({
variant="window"
coverUrl={coverUrl}
bottomPaddingClass={bottomPadding}
onCoverClick={onTitleCardCoverClick}
coverArtAriaLabel={t("apps.ipod.menu.coverFlow")}
/>
)}
</AnimatePresence>
Expand Down Expand Up @@ -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({
Expand All @@ -687,6 +717,7 @@ export function KaraokeFullscreenLyricsOverlay({
lyricsAlignment,
onSwipeUp: onSwipeUpOverride,
onSwipeDown: onSwipeDownOverride,
onTitleCardCoverClick,
}: FullscreenLyricsProps) {
const {
lyricsControls,
Expand Down Expand Up @@ -741,6 +772,8 @@ export function KaraokeFullscreenLyricsOverlay({
variant="fullscreen"
coverUrl={coverUrl}
bottomPaddingClass={bottomPadding}
onCoverClick={onTitleCardCoverClick}
coverArtAriaLabel={t("apps.ipod.menu.coverFlow")}
/>
)}
</AnimatePresence>
Expand Down
8 changes: 8 additions & 0 deletions src/apps/karaoke/hooks/useKaraokeLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -1682,6 +1689,7 @@ export function useKaraokeLogic({
handleAddUrl,
handlePlayTrack,
handleToggleCoverFlow,
handleOpenCoverFlow,
handleCoverFlowSelectTrack,
handleCoverFlowPlayInPlace,
handleCoverFlowRotation,
Expand Down
Loading