feat: track info drawer (Get Info-style)

Add a right-side track info drawer that sits to the right of the queue
panel when both are open. Shows a large cover, title/artist/album links,
a Play/Queue/Edit actions row, and Status/General/File/Identifiers
sections (empty rows omitted). Opens from the track context menu, the
player now-playing tile, and the queue now-playing card.

- ui slice: trackInfoId + open/closeTrackInfo
- TrackInfoDrawer rendered after QueuePanel in AppShell; overlays content
  on narrow viewports
- map source/createdAt/enrichedAt from the wire (were unmapped)
- formatDateTime helper, info icon, i18n (en/ru)
- drop orphaned toggleNowPlaying/isNowPlayingOpen from player slice

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Senko-san
2026-06-13 14:02:38 +03:00
parent 9c344b98c4
commit 8a70f478c3
14 changed files with 641 additions and 16 deletions
+21 -3
View File
@@ -10,6 +10,7 @@ import {
type QueueEntry,
} from '../../store/slices/queue';
import { toggleQueue } from '../../store/slices/player';
import { openTrackInfo } from '../../store/slices/ui';
import { useResolvedQueueEntry } from '../../hooks/useResolvedQueueEntry';
export function QueuePanel() {
@@ -85,14 +86,27 @@ export function QueuePanel() {
<div className="t">{now.title}</div>
<div className="r">{now.artistName}</div>
</div>
<Icon name="cloud" style={{ color: 'var(--fg-3)' }} />
<button
type="button"
className="iconbtn sm"
onClick={() => dispatch(openTrackInfo(now.trackId))}
title={t('trackInfo.open')}
>
<Icon name="info" />
</button>
</div>
{isRadio && (
<div className="qd-radio">
<div className="row">
<Icon name="radio" />
<span style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-1)' }}>
<span
style={{
fontSize: 13,
fontWeight: 600,
color: 'var(--fg-1)',
}}
>
{t('queue.radioActive')}
</span>
<div style={{ flex: 1 }} />
@@ -161,7 +175,11 @@ function QueueRow({
const albumTitle = resolved?.albumTitle ?? entry.albumTitle;
return (
<div className="qrow" onDoubleClick={onPlay} title={t('queue.doubleClickPlay')}>
<div
className="qrow"
onDoubleClick={onPlay}
title={t('queue.doubleClickPlay')}
>
<span className="grip">
<Icon name="dots-six-vertical" />
</span>