feat: UI polish, DnD fix, navigation, and installer improvements (v1.0.10)

- Fix queue DnD on macOS/Windows: delay ref cleanup in onDragEnd so onDropQueue
  reads correct source/destination before dragend clears them
- Active track highlighting in album tracklist (pulsing accent bg + play icon)
- Marquee scrolling for long titles in Fullscreen Player
- Clickable artist/album in Player Bar and Queue now-playing strip
- Tracklist: format column moved after duration, auto width, kHz/filesize removed
- Settings dropdowns: visible border (base bg + overlay0 border)
- Sidebar: fixed responsive width via clamp(), removed drag-to-resize
- Favorites icon: HandMetal → Star in Random Mix page
- Linux app menu category set to Multimedia (AudioVideo)
- Windows MSI: stable upgradeCode for in-place upgrades
- Bundle: category/description fields at correct config level
- About: Claude Code credit, fixed German MIT licence wording

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-03-14 11:36:03 +01:00
parent 32571a2986
commit 623a6a4a54
16 changed files with 177 additions and 72 deletions
+14 -2
View File
@@ -6,6 +6,7 @@ import { usePlayerStore } from '../store/playerStore';
import { buildCoverArtUrl, coverArtCacheKey } from '../api/subsonic';
import CachedImage from './CachedImage';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
function formatTime(seconds: number): string {
if (!seconds || isNaN(seconds)) return '0:00';
@@ -16,6 +17,7 @@ function formatTime(seconds: number): string {
export default function PlayerBar() {
const { t } = useTranslation();
const navigate = useNavigate();
const { currentTrack, isPlaying, progress, buffered, currentTime, volume, togglePlay, next, previous, seek, setVolume, isQueueVisible, toggleQueue, stop, toggleRepeat, repeatMode, toggleFullscreen } = usePlayerStore();
const duration = currentTrack?.duration ?? 0;
@@ -68,10 +70,20 @@ export default function PlayerBar() {
)}
</div>
<div className="player-track-meta">
<div className="player-track-name" data-tooltip={currentTrack?.title ?? ''}>
<div
className="player-track-name"
data-tooltip={currentTrack?.title ?? ''}
style={{ cursor: currentTrack?.albumId ? 'pointer' : 'default' }}
onClick={() => currentTrack?.albumId && navigate(`/album/${currentTrack.albumId}`)}
>
{currentTrack?.title ?? t('player.noTitle')}
</div>
<div className="player-track-artist" data-tooltip={currentTrack?.artist ?? ''}>
<div
className="player-track-artist"
data-tooltip={currentTrack?.artist ?? ''}
style={{ cursor: currentTrack?.artistId ? 'pointer' : 'default' }}
onClick={() => currentTrack?.artistId && navigate(`/artist/${currentTrack.artistId}`)}
>
{currentTrack?.artist ?? '—'}
</div>
</div>