feat: show the player bar volume as a read-only readout
This commit is contained in:
1 parent
51ff98eff1
commit
0345d948ac
7 files changed
+24
-18
No files matched your search
@@ -15,9 +15,7 @@
|
||||
.player-tools { display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
|
||||
.player-tools .volume-control { display: flex; align-items: center; gap: 6px; margin-right: 16px; }
|
||||
.player-tools .volume-slider { width: 90px; accent-color: var(--color-foreground); }
|
||||
.player-tools .volume-input { box-sizing: border-box; width: 4.5ch; min-width: 0; padding: 4px 3px; text-align: center; font-variant-numeric: tabular-nums; -moz-appearance: textfield; }
|
||||
.player-tools .volume-input::-webkit-inner-spin-button, .player-tools .volume-input::-webkit-outer-spin-button { margin: 0; -webkit-appearance: none; }
|
||||
.player-tools .volume-unit { color: var(--color-foreground-subtle); font-size: var(--text-ui-xs); }
|
||||
.player-tools .volume-readout { min-width: 5ch; color: var(--color-foreground-subtle); font-size: var(--text-ui-sm); font-variant-numeric: tabular-nums; }
|
||||
.player-panel-toggle { color: var(--color-foreground-subtle); }
|
||||
.player-panel-toggle:hover:not(:disabled), .player-panel-toggle:focus-visible:not(:disabled), .player-panel-toggle[aria-pressed='true'] { color: var(--color-brand); background: transparent; }
|
||||
.player-panel-toggle:active:not(:disabled) { color: var(--color-brand); background: transparent; transform: none; }
|
||||
|
||||
@@ -4,7 +4,7 @@ import { roomStore } from '@/core/room'
|
||||
import { sourceName } from '@/features/queue'
|
||||
import { formatDuration } from '@/shared/lib/time'
|
||||
import { useStore } from '@/shared/lib/use-store'
|
||||
import { Artwork, AsyncIconButton, IconButton, VolumeInput } from '@/shared/ui'
|
||||
import { Artwork, AsyncIconButton, IconButton } from '@/shared/ui'
|
||||
import { playerStore } from './player-store'
|
||||
import { volumeStore } from './volume-store'
|
||||
import './playback.css'
|
||||
@@ -64,6 +64,7 @@ export function PlayerBar({ onSkip, onLyrics, onQueue, onChat, queueOpen, chatOp
|
||||
const connected = useStore(roomStore, s => s.status === 'open')
|
||||
const volume = useStore(volumeStore, s => s.volume)
|
||||
const muted = useStore(volumeStore, s => s.muted)
|
||||
const audibleVolume = muted ? 0 : volume
|
||||
const meta = nowPlaying?.entry.meta
|
||||
const artist = meta?.artist || '未知艺术家'
|
||||
const source = nowPlaying ? sourceName(nowPlaying.entry.track) : undefined
|
||||
@@ -90,15 +91,23 @@ export function PlayerBar({ onSkip, onLyrics, onQueue, onChat, queueOpen, chatOp
|
||||
</div>
|
||||
<div className="player-tools">
|
||||
<IconButton icon={muted ? VolumeX : Volume2} label={muted ? '取消静音' : '静音'} onClick={() => volumeStore.setMuted(!muted)} />
|
||||
<VolumeInput
|
||||
volume={volume}
|
||||
sliderValue={muted ? 0 : volume}
|
||||
onCommit={(next) => {
|
||||
volumeStore.setVolume(next)
|
||||
if (muted && next > 0)
|
||||
volumeStore.setMuted(false)
|
||||
}}
|
||||
/>
|
||||
<div className="volume-control">
|
||||
<input
|
||||
className="volume-slider"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={audibleVolume}
|
||||
aria-label="音量"
|
||||
onChange={(event) => {
|
||||
const next = Number(event.target.value)
|
||||
volumeStore.setVolume(next)
|
||||
if (muted && next > 0)
|
||||
volumeStore.setMuted(false)
|
||||
}}
|
||||
/>
|
||||
<span className="volume-readout" aria-hidden="true">{`${audibleVolume}%`}</span>
|
||||
</div>
|
||||
<IconButton icon={MessageCircle} label="房间聊天" className="player-panel-toggle" disabled={!canOpenPanels} aria-pressed={chatOpen} onClick={onChat} />
|
||||
<IconButton icon={ListMusic} label="播放列表" className="player-panel-toggle" disabled={!canOpenPanels} aria-pressed={queueOpen} onClick={onQueue} />
|
||||
</div>
|
||||
|
||||
@@ -6,10 +6,11 @@ import { errorMessage } from '@/core/errors'
|
||||
import { historyStore, searchLimits } from '@/features/history'
|
||||
import { reminderStore, requestNotificationPermission, systemNotificationsSupported, volumeStore } from '@/features/playback'
|
||||
import { useStore } from '@/shared/lib/use-store'
|
||||
import { notificationStore, Select, VolumeInput } from '@/shared/ui'
|
||||
import { notificationStore, Select } from '@/shared/ui'
|
||||
import { appearanceStore, fontSizes, themes } from './appearance-store'
|
||||
import { performanceLevels, performanceStore } from './performance-store'
|
||||
import { profileStore } from './profile-store'
|
||||
import { VolumeInput } from './volume-input'
|
||||
import './settings.css'
|
||||
|
||||
interface SettingsDraft {
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -4,13 +4,12 @@ import { beginVolumeEdit, changeVolumeDraft, commitVolumeDraft, initialVolumeEdi
|
||||
interface VolumeInputProps {
|
||||
volume: number
|
||||
onCommit: (volume: number) => void
|
||||
sliderValue?: number
|
||||
id?: string
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export function VolumeInput({ volume, onCommit, sliderValue, id, className = '', disabled = false }: VolumeInputProps) {
|
||||
export function VolumeInput({ volume, onCommit, id, className = '', disabled = false }: VolumeInputProps) {
|
||||
const [editor, setEditor] = useState(() => initialVolumeEditor(volume))
|
||||
const syncedEditor = syncVolumeDraft(editor, volume)
|
||||
const commit = () => {
|
||||
@@ -27,7 +26,7 @@ export function VolumeInput({ volume, onCommit, sliderValue, id, className = '',
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={sliderValue ?? volume}
|
||||
value={volume}
|
||||
aria-label="音量"
|
||||
disabled={disabled}
|
||||
onChange={(event) => {
|
||||
@@ -16,4 +16,3 @@ export { Skeleton } from './skeleton'
|
||||
export { SongArtwork } from './song-artwork'
|
||||
export { SongList } from './song-list'
|
||||
export type { SongAction, SongItem } from './song-list'
|
||||
export { VolumeInput } from './volume-input'
|
||||
Reference in new issue
Block a user