@@ -10,12 +10,15 @@ import type { ReactNode, RefObject } from "react";
1010export function PlayerControls ( ) {
1111 return (
1212 < div className = "flex flex-col gap-4 overflow-hidden" >
13- < div className = "flex justify-center" >
13+ < div className = "flex justify-center items-center " >
1414 < PlayButton />
15+ < div className = "ml-auto max-w-64 w-full" >
16+ < Qualities />
17+ </ div >
1518 </ div >
1619 < div className = "p-3 rounded-md bg-default-100" >
17- < Time />
1820 < Seekbar />
21+ < Time />
1922 </ div >
2023 < Tracks />
2124 </ div >
@@ -78,31 +81,37 @@ function Seekbar() {
7881 }
7982
8083 return (
81- < div { ...seekbar . rootProps } className = "w-full relative cursor-pointer" >
84+ < div { ...seekbar . rootProps } className = "w-full relative cursor-pointer py-2 " >
8285 < Tooltip
8386 x = { seekbar . x }
8487 seekbarRef = { seekbar . rootProps . ref }
8588 visible = { seekbar . active }
8689 >
8790 { hms ( seekbar . value ) }
8891 </ Tooltip >
89- < div className = "relative flex items-center" >
90- < div className = "h-2 bg-default-200 w-full" />
92+ < div className = "relative flex items-center h-1 " >
93+ < div className = "h-1 bg-default-200 w-full" />
9194 < div
9295 className = { cn (
93- "h-2 absolute left-0 right-0 bg-default-300 origin-left opacity-0 transition-opacity" ,
96+ "h-1 absolute left-0 right-0 bg-default-300 origin-left opacity-0 transition-opacity" ,
9497 seekbar . hover && "opacity-100" ,
9598 ) }
9699 style = { {
97100 transform : `scaleX(${ seekbar . x } )` ,
98101 } }
99102 />
100103 < div
101- className = { cn ( "h-2 absolute left-0 right-0 bg-black origin-left" ) }
104+ className = { cn ( "h-1 absolute left-0 right-0 bg-black origin-left" ) }
102105 style = { {
103106 transform : `scaleX(${ percentage } )` ,
104107 } }
105108 />
109+ < div
110+ className = "h-4 absolute w-[3px] bg-black rounded-full -translate-x-1/2 outline-default-100 outline outline-2 z-10"
111+ style = { {
112+ left : `${ percentage * 100 } %` ,
113+ } }
114+ />
106115 </ div >
107116 < CuePoints />
108117 </ div >
@@ -137,7 +146,7 @@ function Tooltip({
137146 < div
138147 ref = { ref }
139148 className = { cn (
140- "pointer-events-none absolute h-6 -top-8 -translate-x-1/2 opacity-0 transition-opacity text-xs text-white bg-black px-1 flex items-center rounded-md" ,
149+ "pointer-events-none absolute h-6 -top-6 -translate-x-1/2 opacity-0 transition-opacity text-xs text-white bg-black px-1 flex items-center rounded-md" ,
141150 visible && "opacity-100" ,
142151 ) }
143152 style = { {
@@ -155,7 +164,7 @@ function CuePoints() {
155164 const seekableStart = usePlayerSelector ( ( player ) => player . seekableStart ) ;
156165
157166 return (
158- < div className = "relative h-4 bg-gray-100 rounded-lg " >
167+ < div className = "relative h-4" >
159168 { cuePoints . map ( ( cuePoint ) => {
160169 return (
161170 < div
@@ -227,6 +236,29 @@ function Tracks() {
227236 ) ;
228237}
229238
239+ function Qualities ( ) {
240+ const qualities = usePlayerSelector ( ( player ) => player . qualities ) ;
241+ const autoQuality = usePlayerSelector ( ( player ) => player . autoQuality ) ;
242+ const setQuality = usePlayerSelector ( ( player ) => player . setQuality ) ;
243+
244+ return (
245+ < Selection
246+ items = { [
247+ ...qualities ,
248+ {
249+ height : null ,
250+ active : autoQuality ,
251+ } ,
252+ ] }
253+ label = "Quality"
254+ getActive = { ( item ) => item . active }
255+ getKey = { ( item ) => item . height }
256+ getLabel = { ( item ) => item . height ?. toString ( ) ?? "Auto" }
257+ onChange = { ( item ) => setQuality ( item . height ) }
258+ />
259+ ) ;
260+ }
261+
230262function hms ( seconds : number ) {
231263 return (
232264 new Date ( seconds * 1000 ) . toUTCString ( ) . match ( / ( \d \d : \d \d : \d \d ) / ) ?. [ 0 ] ??
0 commit comments