mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
feat: Rust audio engine, genre mix, queue shuffle, and UX improvements (v1.2.0)
### Audio Engine - Replace Howler.js with native Rust/rodio backend (src-tauri/src/audio.rs) - audio_play/pause/resume/stop/seek/set_volume Tauri commands - Generation counter cancels stale in-flight downloads on skip - Wall-clock position tracking; audio:ended after 2 ticks near end ### Playback Persistence - Persist currentTrack, queue, queueIndex, currentTime to localStorage - Cold-start resume: play + seek to saved position on app restart - Position priority: server queue > localStorage ### Random Mix - Genre blacklist: excludeAudiobooks toggle + custom chip-based blacklist - Clickable genre chips in tracklist to blacklist on the fly - Super Genre Mix: 9 genres, progressive rendering, Load 10 more - Promise.allSettled + 45s timeout for large Metal/Rock libraries - Two-column filter panel at top of page ### Queue & UI - Shuffle button in queue header (Fisher-Yates, keeps current track at 0) - LiveSearch arrow key / Enter / Escape keyboard navigation - Multi-line tooltip support (data-tooltip-wrap attribute) - Update link uses Tauri shell open() to launch system browser - Sidebar min-width 180px → 200px (fixes Psysonic title clipping) - Tooltip z-index fix: main-content z-index:1 over queue panel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
-4
@@ -145,6 +145,19 @@ const enTranslation = {
|
||||
favoriteAdd: 'Add to Favorites',
|
||||
favoriteRemove: 'Remove from Favorites',
|
||||
play: 'Play',
|
||||
trackGenre: 'Genre',
|
||||
excludeAudiobooks: 'Exclude audiobooks & radio plays',
|
||||
excludeAudiobooksDesc: 'Filters genres: Hörbuch, Hörspiel, Audiobook, Spoken Word, …',
|
||||
genreBlocked: 'Genre blocked',
|
||||
genreAddedToBlacklist: 'Added to blacklist',
|
||||
genreAlreadyBlocked: 'Already blocked',
|
||||
blacklistToggle: 'Genre Blacklist',
|
||||
genreMixTitle: 'Genre Mix',
|
||||
genreMixDesc: 'Select a genre to get a curated random mix',
|
||||
genreMixLoadMore: 'Load 10 more',
|
||||
genreMixNoGenres: 'No genres found on server.',
|
||||
filterPanelTitle: 'Filters',
|
||||
genreClickHint: 'Click a genre tag\nto add it to your blacklist.\nExcluded from future mixes.',
|
||||
},
|
||||
playlists: {
|
||||
title: 'Playlists',
|
||||
@@ -261,8 +274,15 @@ const enTranslation = {
|
||||
aboutLicenseText: 'MIT — free to use, modify, and distribute.',
|
||||
aboutRepo: 'Source Code on GitHub',
|
||||
aboutVersion: 'Version',
|
||||
aboutBuiltWith: 'Built with Tauri · React · TypeScript · Howler.js',
|
||||
aboutAiCredit: 'Developed with the support of Claude Code by Anthropic'
|
||||
aboutBuiltWith: 'Built with Tauri · React · TypeScript · Rust/rodio',
|
||||
aboutAiCredit: 'Developed with the support of Claude Code by Anthropic',
|
||||
randomMixTitle: 'Random Mix',
|
||||
randomMixBlacklistTitle: 'Custom Genre Blacklist',
|
||||
randomMixBlacklistDesc: 'Songs whose genre matches an entry in this list are excluded from the Random Mix (when "Exclude audiobooks" is active).',
|
||||
randomMixBlacklistPlaceholder: 'Add genre…',
|
||||
randomMixBlacklistAdd: 'Add',
|
||||
randomMixBlacklistEmpty: 'No custom genres added yet.',
|
||||
randomMixHardcodedTitle: 'Built-in exclusions (active when checkbox is on)',
|
||||
},
|
||||
help: {
|
||||
title: 'Help',
|
||||
@@ -328,6 +348,7 @@ const enTranslation = {
|
||||
delete: 'Delete',
|
||||
deleteConfirm: 'Delete playlist "{{name}}"?',
|
||||
clear: 'Clear',
|
||||
shuffle: 'Shuffle queue',
|
||||
hide: 'Hide',
|
||||
close: 'Close',
|
||||
nextTracks: 'Next Tracks',
|
||||
@@ -506,6 +527,19 @@ const deTranslation = {
|
||||
favoriteAdd: 'Zu Favoriten hinzufügen',
|
||||
favoriteRemove: 'Aus Favoriten entfernen',
|
||||
play: 'Abspielen',
|
||||
trackGenre: 'Genre',
|
||||
excludeAudiobooks: 'Hörbücher & Hörspiele ausschließen',
|
||||
excludeAudiobooksDesc: 'Filtert Genres: Hörbuch, Hörspiel, Audiobook, Spoken Word, …',
|
||||
genreBlocked: 'Genre gesperrt',
|
||||
genreAddedToBlacklist: 'Zur Blacklist hinzugefügt',
|
||||
genreAlreadyBlocked: 'Bereits gesperrt',
|
||||
blacklistToggle: 'Genre-Blacklist',
|
||||
genreMixTitle: 'Genre-Mix',
|
||||
genreMixDesc: 'Genre auswählen für einen passenden Zufallsmix',
|
||||
genreMixLoadMore: '10 weitere laden',
|
||||
genreMixNoGenres: 'Keine Genres auf dem Server gefunden.',
|
||||
filterPanelTitle: 'Filter',
|
||||
genreClickHint: 'Genre-Tag anklicken,\num es zur Blacklist hinzuzufügen.\nBeim nächsten Mix ausgeschlossen.',
|
||||
},
|
||||
playlists: {
|
||||
title: 'Playlists',
|
||||
@@ -622,8 +656,15 @@ const deTranslation = {
|
||||
aboutLicenseText: 'MIT — kostenlos nutzbar, veränderbar und weiterzugeben.',
|
||||
aboutRepo: 'Quellcode auf GitHub',
|
||||
aboutVersion: 'Version',
|
||||
aboutBuiltWith: 'Gebaut mit Tauri · React · TypeScript · Howler.js',
|
||||
aboutAiCredit: 'Mit freundlicher Unterstützung von Claude Code by Anthropic'
|
||||
aboutBuiltWith: 'Gebaut mit Tauri · React · TypeScript · Rust/rodio',
|
||||
aboutAiCredit: 'Mit freundlicher Unterstützung von Claude Code by Anthropic',
|
||||
randomMixTitle: 'Zufallsmix',
|
||||
randomMixBlacklistTitle: 'Eigene Genre-Blacklist',
|
||||
randomMixBlacklistDesc: 'Songs, deren Genre einem Eintrag in dieser Liste entspricht, werden aus dem Zufallsmix ausgeschlossen (wenn „Hörbücher ausschließen" aktiv ist).',
|
||||
randomMixBlacklistPlaceholder: 'Genre hinzufügen…',
|
||||
randomMixBlacklistAdd: 'Hinzufügen',
|
||||
randomMixBlacklistEmpty: 'Noch keine eigenen Genres hinzugefügt.',
|
||||
randomMixHardcodedTitle: 'Eingebaute Ausschlüsse (aktiv wenn Checkbox an)',
|
||||
},
|
||||
help: {
|
||||
title: 'Hilfe',
|
||||
@@ -689,6 +730,7 @@ const deTranslation = {
|
||||
delete: 'Löschen',
|
||||
deleteConfirm: 'Playlist "{{name}}" löschen?',
|
||||
clear: 'Leeren',
|
||||
shuffle: 'Queue mischen',
|
||||
hide: 'Verbergen',
|
||||
close: 'Schließen',
|
||||
nextTracks: 'Nächste Titel',
|
||||
|
||||
Reference in New Issue
Block a user