diff --git a/src/components/player/Player.tsx b/src/components/player/Player.tsx
index c428328..a7c0642 100644
--- a/src/components/player/Player.tsx
+++ b/src/components/player/Player.tsx
@@ -21,7 +21,6 @@ import { Playlist } from './Playlist'
import { PlayerControls } from './PlayerControls'
import { PlayerProgress } from './PlayerProgress'
import { PlayerTrackInfo } from './PlayerTrackInfo'
-import { PlayerVolume } from './PlayerVolume'
import { useRenderFlash } from '@/hooks/useRenderFlash'
export type PlayerDisplayMode = 'normal' | 'minimized' | 'maximized' | 'sidebar'
@@ -347,22 +346,17 @@ export function Player({ className, onPlayerModeChange }: PlayerProps) {
mode={state.mode}
isLoading={isLoading}
showPlaylistButton={true}
+ volume={state.volume}
onPlayPause={handlePlayPause}
onStop={handleStop}
onPrevious={handlePrevious}
onNext={handleNext}
onModeChange={handleModeChange}
onTogglePlaylist={() => setShowPlaylist(!showPlaylist)}
+ onVolumeChange={handleVolumeChange}
+ onMute={handleMute}
/>
-
-
{/* Playlist */}
{showPlaylist && state.playlist && (
@@ -429,16 +423,12 @@ export function Player({ className, onPlayerModeChange }: PlayerProps) {
status={state.status}
mode={state.mode}
isLoading={isLoading}
+ volume={state.volume}
onPlayPause={handlePlayPause}
onStop={handleStop}
onPrevious={handlePrevious}
onNext={handleNext}
onModeChange={handleModeChange}
- variant="maximized"
- />
-
-
void
onStop: () => void
onPrevious: () => void
onNext: () => void
onModeChange: () => void
onTogglePlaylist?: () => void
+ onVolumeChange?: (volume: number[]) => void
+ onMute?: () => void
variant?: 'normal' | 'maximized' | 'minimized'
}
@@ -36,17 +42,20 @@ export const PlayerControls = memo(function PlayerControls({
mode,
isLoading,
showPlaylistButton = false,
+ volume,
onPlayPause,
onStop,
onPrevious,
onNext,
onModeChange,
onTogglePlaylist,
+ onVolumeChange,
+ onMute,
variant = 'normal',
}: PlayerControlsProps) {
const isMinimized = variant === 'minimized'
const isMaximized = variant === 'maximized'
- const flashClass = useRenderFlash([status, mode], 'green')
+ const flashClass = useRenderFlash([status, mode, volume], 'green')
const modeIcon = useMemo(() => {
switch (mode) {
@@ -168,6 +177,30 @@ export const PlayerControls = memo(function PlayerControls({
{modeLabel}
+
+ {volume !== undefined && onVolumeChange && onMute && (
+
+
+
+
+
+
+ {Math.round(volume)}%
+
+
+ )}
)
@@ -242,6 +275,32 @@ export const PlayerControls = memo(function PlayerControls({
{modeLabel}
+
+ {volume !== undefined && onVolumeChange && onMute && (
+
+
+
+
+
+
+ )}
)
diff --git a/src/components/player/PlayerProgress.tsx b/src/components/player/PlayerProgress.tsx
index 1d6dfe1..88a0a6b 100644
--- a/src/components/player/PlayerProgress.tsx
+++ b/src/components/player/PlayerProgress.tsx
@@ -18,7 +18,11 @@ export const PlayerProgress = memo(function PlayerProgress({
variant = 'normal',
}: PlayerProgressProps) {
const isMaximized = variant === 'maximized'
- const flashClass = useRenderFlash([position, duration], 'blue')
+
+ // Only flash when seconds actually change to avoid NumberFlow timing issues
+ const positionSeconds = Math.floor(position / 1000)
+ const durationSeconds = Math.floor(duration / 1000)
+ const flashClass = useRenderFlash([positionSeconds, durationSeconds], 'blue')
const progressPercentage = useMemo(() =>
(position / (duration || 1)) * 100,
diff --git a/src/components/player/PlayerVolume.tsx b/src/components/player/PlayerVolume.tsx
deleted file mode 100644
index 80cfb5e..0000000
--- a/src/components/player/PlayerVolume.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import { Button } from '@/components/ui/button'
-import { Slider } from '@/components/ui/slider'
-import { Volume2, VolumeX } from 'lucide-react'
-import { memo } from 'react'
-import { useRenderFlash } from '@/hooks/useRenderFlash'
-
-interface PlayerVolumeProps {
- volume: number
- onVolumeChange: (volume: number[]) => void
- onMute: () => void
- variant?: 'normal' | 'maximized'
-}
-
-export const PlayerVolume = memo(function PlayerVolume({
- volume,
- onVolumeChange,
- onMute,
- variant = 'normal',
-}: PlayerVolumeProps) {
- const isMaximized = variant === 'maximized'
- const flashClass = useRenderFlash([volume], 'yellow')
-
- if (isMaximized) {
- return (
-
- {/* DEBUG: PlayerVolume Maximized - YELLOW FLASH */}
-
-
-
-
-
- {Math.round(volume)}%
-
-
- )
- }
-
- // Normal variant
- return (
-
- {/* DEBUG: PlayerVolume Normal - YELLOW FLASH */}
-
-
-
-
-
- )
-})
\ No newline at end of file
diff --git a/src/hooks/useRenderFlash.ts b/src/hooks/useRenderFlash.ts
index 6f34138..6fd0bf1 100644
--- a/src/hooks/useRenderFlash.ts
+++ b/src/hooks/useRenderFlash.ts
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'
export function useRenderFlash(deps: any[], color: string = 'red', duration: number = 300) {
const [isFlashing, setIsFlashing] = useState(false)
- const prevDepsRef = useRef()
+ const prevDepsRef = useRef(undefined)
useEffect(() => {
// Check if this is the first render
@@ -25,7 +25,7 @@ export function useRenderFlash(deps: any[], color: string = 'red', duration: num
}
prevDepsRef.current = deps
- }, deps)
+ }, [...deps])
const flashClass = isFlashing
? `border-2 border-${color}-500 border-dashed animate-pulse`