Move project from bordanlage/ to repo root
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
90
dashboard/src/components/audio/NowPlaying.jsx
Normal file
90
dashboard/src/components/audio/NowPlaying.jsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { usePlayer } from '../../hooks/usePlayer.js'
|
||||
|
||||
function formatTime(ms) {
|
||||
if (!ms) return '0:00'
|
||||
const s = Math.floor(ms / 1000)
|
||||
return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
export default function NowPlaying({ compact = false }) {
|
||||
const { currentTrack, state, position, play, pause, next, previous, connected } = usePlayer()
|
||||
|
||||
if (!connected) {
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<span style={{ color: 'var(--muted)', fontSize: 13 }}>Audio not connected</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const progress = currentTrack?.duration
|
||||
? Math.min(100, (position / currentTrack.duration) * 100)
|
||||
: 0
|
||||
|
||||
return (
|
||||
<div style={{ ...styles.container, ...(compact ? styles.compact : {}) }}>
|
||||
{/* Cover placeholder */}
|
||||
<div style={styles.cover}>
|
||||
{currentTrack?.coverUrl
|
||||
? <img src={currentTrack.coverUrl} alt="cover" style={styles.coverImg} />
|
||||
: <span style={styles.coverIcon}>♫</span>}
|
||||
</div>
|
||||
|
||||
<div style={styles.info}>
|
||||
<div style={styles.title}>{currentTrack?.title || 'Nothing playing'}</div>
|
||||
<div style={styles.artist}>{currentTrack?.artist || ''}</div>
|
||||
{!compact && <div style={styles.album}>{currentTrack?.album || ''}</div>}
|
||||
|
||||
{/* Progress bar */}
|
||||
{currentTrack && (
|
||||
<div style={styles.progressRow}>
|
||||
<span style={styles.timeText}>{formatTime(position)}</span>
|
||||
<div style={styles.progressBg}>
|
||||
<div style={{ ...styles.progressFill, width: `${progress}%` }} />
|
||||
</div>
|
||||
<span style={styles.timeText}>{formatTime(currentTrack.duration)}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Controls */}
|
||||
<div style={styles.controls}>
|
||||
<button style={styles.btn} onClick={previous}>⏮</button>
|
||||
<button style={{ ...styles.btn, ...styles.playBtn }}
|
||||
onClick={state === 'playing' ? pause : play}>
|
||||
{state === 'playing' ? '⏸' : '▶'}
|
||||
</button>
|
||||
<button style={styles.btn} onClick={next}>⏭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = {
|
||||
container: {
|
||||
display: 'flex', gap: 16, padding: 16,
|
||||
background: 'var(--surface)', borderRadius: 'var(--radius)',
|
||||
border: '1px solid var(--border)',
|
||||
alignItems: 'center',
|
||||
},
|
||||
compact: { padding: '10px 14px' },
|
||||
cover: {
|
||||
width: 64, height: 64, flexShrink: 0,
|
||||
background: 'var(--surface2)', borderRadius: 6,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
coverImg: { width: '100%', height: '100%', objectFit: 'cover' },
|
||||
coverIcon: { fontSize: 28, color: 'var(--muted)' },
|
||||
info: { flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 4 },
|
||||
title: { fontWeight: 600, fontSize: 14, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' },
|
||||
artist: { fontSize: 12, color: 'var(--muted)' },
|
||||
album: { fontSize: 11, color: 'var(--muted)', opacity: 0.7 },
|
||||
progressRow: { display: 'flex', alignItems: 'center', gap: 8, marginTop: 4 },
|
||||
progressBg: { flex: 1, height: 3, background: 'var(--border)', borderRadius: 2, overflow: 'hidden' },
|
||||
progressFill: { height: '100%', background: 'var(--accent)', borderRadius: 2, transition: 'width 1s linear' },
|
||||
timeText: { fontSize: 10, color: 'var(--muted)', fontFamily: 'var(--font-mono)', minWidth: 30 },
|
||||
controls: { display: 'flex', gap: 4, marginTop: 4 },
|
||||
btn: { width: 36, height: 36, fontSize: 14, background: 'var(--surface2)', color: 'var(--text)', minWidth: 36 },
|
||||
playBtn: { background: 'var(--accent)', color: '#000', fontWeight: 700 },
|
||||
}
|
||||
Reference in New Issue
Block a user