Skip to content

Commit da23de0

Browse files
Added support for media keys and notification artwork
1 parent a31f4f9 commit da23de0

File tree

6 files changed

+137
-53
lines changed

6 files changed

+137
-53
lines changed

app/album/[id]/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export default function Page({ params }: { params: Promise<{ id: string }> }) {
231231
</div>
232232
<div className={`flex gap-4 items-center p-6 md:p-12 overflow-x-hidden pt-16 w-full justify-center md:justify-normal border-b-2 border-b-primary-foreground`}>
233233
<div className='flex flex-col md:flex-row items-center gap-5'>
234-
<Image src={`/song-files/covers/${id.toLowerCase()}.jpg`} alt={id} width={imageSize} height={imageSize} className='md:mt-4 rounded-xl outline outline-primary/10' />
234+
<Image src={`/song-files/covers/${id.toLowerCase()}.jpg`} alt={id} width={imageSize} height={imageSize} priority={true} className='md:mt-4 rounded-xl outline outline-primary/10' />
235235
<div className='flex flex-col gap-2'>
236236
<div className='text-4xl font-semibold text-center md:text-left'>{albumName}</div>
237237
<div className='inline-flex items-center justify-center md:justify-normal'>
@@ -273,7 +273,7 @@ export default function Page({ params }: { params: Promise<{ id: string }> }) {
273273
<div className='relative w-full items-center ml-6 md:ml-2 select-none'>
274274
<div className='flex justify-between w-full'>
275275
<div className="flex items-center w-full">
276-
<div className="text-sm md:text-md font-semibold whitespace-nowrap overflow-hidden text-ellipsis tracking-wide">
276+
<div className="text-sm md:text-md font-semibold tracking-wide">
277277
{element.title}
278278
</div>
279279
<Dot className='-mx-1 hidden md:block text-primary/60' />

app/testing/page.tsx

+1-5
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ export default function Page() {
5252
return acc;
5353
}, {} as Record<string, any[]>);
5454

55-
const sortedYears = Object.keys(filteredEntries).sort((a, b) => {
56-
const rowA = parseInt(a.replace("row ", ""));
57-
const rowB = parseInt(b.replace("row ", ""));
58-
return rowA / rowB; // Sort numerically by row
59-
});
55+
const sortedYears = Object.keys(filteredEntries).sort();
6056

6157
return (
6258
<>

components/songControls.tsx

+90-29
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Drawer, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, D
1010
import { Progress } from "./ui/progress";
1111

1212
import '@public/CSS/song-controls.css';
13+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
1314

1415
interface songControlsInterface {
1516
songRef: any;
@@ -57,18 +58,8 @@ export const SongControls = ({
5758
const [appearBar, setAppearBar] = useState(true);
5859
const [optAppear, setOptAppear] = useState(optionalAppear);
5960
const [mediumScreen, setMediumScreen] = useState(false);
60-
61-
useEffect(() => {
62-
const isScreenSmall = () => {
63-
if (window.innerWidth < 768) setMediumScreen(true);
64-
else setMediumScreen(false);
65-
};
66-
isScreenSmall();
67-
68-
window.addEventListener("resize", isScreenSmall);
69-
70-
return () => window.addEventListener("resize", isScreenSmall);
71-
});
61+
const [currentTimeVal, setCurrentTimeVal] = useState(0);
62+
const [songTime, setSongtime] = useState(0);
7263

7364
const pressedKeyOne = useEffect(() => {
7465
const handleKeyDown = (e: KeyboardEvent) => {
@@ -117,10 +108,13 @@ export const SongControls = ({
117108

118109
const updateTime = () => {
119110
if (song.duration) {
120-
setSliderValue(Number(((song.currentTime / song.duration) * 100).toFixed(0)));
111+
setSliderValue((song.currentTime / song.duration) * 100);
121112
}
113+
setCurrentTimeVal(song.currentTime);
122114
};
123115

116+
setSongtime(song.duration);
117+
124118
song.addEventListener("timeupdate", updateTime);
125119

126120
return () => {
@@ -136,6 +130,67 @@ export const SongControls = ({
136130
useEffectConst();
137131
}, [handleSkipSong]);
138132

133+
useEffect(() => {
134+
const isScreenSmall = () => {
135+
if (window.innerWidth < 768) setMediumScreen(true);
136+
else setMediumScreen(false);
137+
};
138+
isScreenSmall();
139+
140+
window.addEventListener("resize", isScreenSmall);
141+
142+
return () => window.addEventListener("resize", isScreenSmall);
143+
});
144+
145+
// this basically just adds support for stuff like media buttons and mobile media players in notification tray
146+
147+
// had never heard of this before but i guess better late than never
148+
useEffect(() => {
149+
const song = songRef.current;
150+
if (!song) return;
151+
152+
navigator.mediaSession.setActionHandler('play', () => setIsPlaying(true));
153+
navigator.mediaSession.setActionHandler('pause', () => setIsPlaying(false));
154+
navigator.mediaSession.setActionHandler('previoustrack', () => handleSkipSong(true));
155+
navigator.mediaSession.setActionHandler('nexttrack', () => handleSkipSong(false));
156+
157+
if ("mediaSession" in navigator) {
158+
navigator.mediaSession.metadata = new MediaMetadata({
159+
title: songVal,
160+
artist: songCreator,
161+
album: "Yandhi",
162+
artwork: [
163+
{
164+
src: image,
165+
sizes: "96x96",
166+
type: "image/png",
167+
},
168+
],
169+
});
170+
}
171+
172+
try {
173+
const setPositionState = () => {
174+
if ('setPositionState' in navigator.mediaSession) {
175+
navigator.mediaSession.setPositionState({
176+
duration: songTime || 0, position: currentTimeVal || 0,
177+
});
178+
}
179+
}
180+
181+
setPositionState();
182+
183+
song.addEventListener("ended", setPositionState());
184+
185+
return () => {
186+
song.removeEventListener("ended", setPositionState());
187+
}
188+
} catch (e) {
189+
console.log(e);
190+
}
191+
192+
}, [handleSkipSong, isPlaying, currentTimeVal, songTime]);
193+
139194
return (
140195
<>
141196
{!mediumScreen ? (
@@ -144,7 +199,7 @@ export const SongControls = ({
144199
left-1/2 -translate-x-1/2 py-3 px-3 bg-primary-foreground/80 backdrop-blur-lg border-2 border-secondary
145200
flex items-center transition-all duration-500 shadow-lg ${appearBar ? "translate-y-0" : "translate-y-24"
146201
}`}
147-
// onClick={hideControls}
202+
onClick={hideControls}
148203
onKeyDown={(e) => pressedKeyOne}
149204
>
150205
<DefaultSongControls
@@ -318,7 +373,7 @@ const DefaultSongControls = ({
318373
</div>
319374
</div>
320375

321-
<div className="flex flex-col justify-center gap-1 w-full">
376+
<div className="flex flex-col justify-center gap-1 w-full" onClick={(e) => e.stopPropagation()}>
322377
<div className="flex justify-center gap-2 ml-2">
323378
<Button
324379
size="icon"
@@ -417,28 +472,27 @@ const SongControlsSmall = ({
417472

418473
return (
419474
<>
420-
<div className="flex flex-col">
421-
<div className="flex items-center py-3 px-3">
422-
<div className="flex items-center gap-2 flex-1 select-none">
475+
<div className="flex flex-col w-full">
476+
<div className="flex items-center py-3 px-3 justify-between">
477+
<div className="flex items-center gap-2 flex-1 select-none max-w-[70%] shadowed-text relative">
423478
<Image
424479
src={image}
425480
alt={image}
426481
width={60}
427482
height={60}
428483
className="rounded-lg"
429484
/>
430-
<div>
431-
<div className="font-semibold overflow-hidden whitespace-nowrap text-ellipsis w-[40vw]">
485+
<div className="overflow-hidden">
486+
<div className="font-semibold overflow-hidden whitespace-pre text-ellipsis w-fit shadowed-text-div">
432487
{songVal !== "" ? songVal : "No Track Found"}
433488
</div>
434-
<div className="text-sm text-muted-foreground">{songCreator}</div>
489+
<div className="text-sm text-muted-foreground">
490+
{songCreator}
491+
</div>
435492
</div>
436493
</div>
437494

438-
<div
439-
className="flex justify-center gap-1"
440-
onClick={(e) => e.stopPropagation()}
441-
>
495+
<div className="flex justify-end gap-1" onClick={(e) => e.stopPropagation()}>
442496
<Button
443497
className={`p-5 rounded-full ${songVal !== "" ? "" : "opacity-50 cursor-not-allowed"}`}
444498
size="icon"
@@ -516,9 +570,7 @@ const MiniPlayer = ({
516570
}, [handleSkipSong]);
517571

518572
return (
519-
<div
520-
className={`p-8 flex flex-col gap-2 transition-all bg-primary-foreground`}
521-
>
573+
<div className={`p-8 flex flex-col gap-2 transition-all bg-primary-foreground w-full`}>
522574
{/* <Button variant='outline' size='icon' onClick={() => setAppear(false)} className="bg-transparent border-none cursor-pointer absolute top-3 left-3 rounded-full">
523575
<ChevronDown />
524576
</Button> */}
@@ -534,7 +586,16 @@ const MiniPlayer = ({
534586
/>
535587
</div>
536588
<div className="flex flex-col overflow-hidden">
537-
<div className="text-2xl font-semibold w-full overflow-hidden whitespace-pre scrolling-text relative">{songVal || "Unknown"}</div>
589+
<TooltipProvider>
590+
<Tooltip delayDuration={0}>
591+
<TooltipTrigger asChild>
592+
<div className="text-2xl font-semibold w-full overflow-hidden whitespace-pre scrolling-text relative select-none">{songVal || "Unknown"}</div>
593+
</TooltipTrigger>
594+
<TooltipContent className="bg-secondary px-2 py-1 rounded-full" align="start">
595+
<div className="z-50">{songVal}</div>
596+
</TooltipContent>
597+
</Tooltip>
598+
</TooltipProvider>
538599
<div className="text-md text-muted-foreground -translate-y-1">
539600
{songCreator || "Unknown"}
540601
</div>

components/ui/tooltip.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
5+
6+
import { cn } from "@/lib/utils"
7+
8+
const TooltipProvider = TooltipPrimitive.Provider
9+
10+
const Tooltip = TooltipPrimitive.Root
11+
12+
const TooltipTrigger = TooltipPrimitive.Trigger
13+
14+
const TooltipContent = React.forwardRef<
15+
React.ElementRef<typeof TooltipPrimitive.Content>,
16+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
17+
>(({ className, sideOffset = 4, ...props }, ref) => (
18+
<TooltipPrimitive.Portal>
19+
<TooltipPrimitive.Content
20+
ref={ref}
21+
sideOffset={sideOffset}
22+
className={cn(
23+
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
24+
className
25+
)}
26+
{...props}
27+
/>
28+
</TooltipPrimitive.Portal>
29+
))
30+
TooltipContent.displayName = TooltipPrimitive.Content.displayName
31+
32+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

next.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const withMDX = createMDX({
3535
//@ts-ignore
3636
'rehype-pretty-code',
3737
{
38-
theme: "dark-plus"
38+
theme: "github-dark"
3939
}
4040
]
4141
],

public/CSS/song-controls.css

+11-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,3 @@
1-
@keyframes example1 {
2-
0% {
3-
transform: translateX(100%);
4-
}
5-
100% {
6-
transform: translateX(-100%);
7-
}
8-
}
9-
10-
.scrolling-text {
11-
/* transform: translateX(100%); */
12-
13-
/* animation: example1 10s linear infinite reverse; */
14-
}
15-
16-
171
.scrolling-text::after, .scrolling-text::before {
182
content: "";
193
position: absolute;
@@ -30,4 +14,15 @@
3014

3115
.scrolling-text::after {
3216
right: 0;
17+
}
18+
19+
.shadowed-text::after {
20+
content: "";
21+
position: absolute;
22+
top: 50%;
23+
transform: translateY(-50%);
24+
right: -10px;
25+
background: linear-gradient(90deg, transparent 0%, hsl(var(--primary-foreground)) 65%);
26+
width: 2.5em;
27+
height: 6em;
3328
}

0 commit comments

Comments
 (0)