mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
feat(tray): show now-playing track in tray + i18n menu labels (#395)
* feat(tray): show now-playing track in tray icon tooltip
Mirrors the current track to the tray tooltip ("Artist – Title") on every
play/pause/track change, falling back to "Psysonic" when nothing is playing.
The cached value survives tray hide/show via a new TrayTooltip state, and
is truncated to 127 chars for Windows NOTIFYICONDATA.szTip.
Closes #383
* feat(tray): linux fallback — disabled menu item shows now-playing track
AppIndicator on Linux has no hover-tooltip API, so the tooltip command was
a silent no-op there. Adds a disabled menu entry at the top of the tray
right-click menu that mirrors the same text. Updated in lockstep with the
Win/macOS tooltip via set_tray_tooltip.
* i18n(tray): localize tray menu labels
Adds a `tray` namespace in all 8 locales (en/de/fr/nl/zh/nb/ru/es) for
Play/Pause, Next/Previous, Show/Hide, Exit, and the Linux-only
"Nothing playing" placeholder.
Rust side: TrayMenuLabels state holds the cached translations and
TrayMenuItems holds the live MenuItem handles. New set_tray_menu_labels
command pushes new strings + applies them via set_text without rebuilding
the tray icon.
Frontend pushes the labels on mount and on every i18n.on('languageChanged').
This commit is contained in:
committed by
GitHub
parent
20a083a9a6
commit
2ea22635e5
+21
-1
@@ -152,7 +152,7 @@ function shouldSuppressQueueResizerMouseDown(clientX: number, clientY: number, q
|
||||
}
|
||||
|
||||
function AppShell() {
|
||||
const { t } = useTranslation();
|
||||
const { t, i18n } = useTranslation();
|
||||
const isMobile = useIsMobile();
|
||||
const [isWindowFullscreen, setIsWindowFullscreen] = useState(false);
|
||||
const [isTilingWm, setIsTilingWm] = useState(false);
|
||||
@@ -311,15 +311,35 @@ function AppShell() {
|
||||
const title = `${state} ${currentTrack.artist} - ${currentTrack.title} | Psysonic`;
|
||||
document.title = title;
|
||||
await appWindow.setTitle(title);
|
||||
await invoke('set_tray_tooltip', {
|
||||
tooltip: `${currentTrack.artist} – ${currentTrack.title}`,
|
||||
}).catch(() => {});
|
||||
} else {
|
||||
document.title = 'Psysonic';
|
||||
await appWindow.setTitle('Psysonic');
|
||||
await invoke('set_tray_tooltip', { tooltip: '' }).catch(() => {});
|
||||
}
|
||||
} catch (err) {}
|
||||
};
|
||||
fn();
|
||||
}, [currentTrack, isPlaying]);
|
||||
|
||||
useEffect(() => {
|
||||
const apply = () => {
|
||||
invoke('set_tray_menu_labels', {
|
||||
playPause: t('tray.playPause'),
|
||||
next: t('tray.nextTrack'),
|
||||
previous: t('tray.previousTrack'),
|
||||
showHide: t('tray.showHide'),
|
||||
quit: t('tray.exitPsysonic'),
|
||||
nothingPlaying: t('tray.nothingPlaying'),
|
||||
}).catch(() => {});
|
||||
};
|
||||
apply();
|
||||
i18n.on('languageChanged', apply);
|
||||
return () => { i18n.off('languageChanged', apply); };
|
||||
}, [t, i18n]);
|
||||
|
||||
// Post-update changelog is now surfaced via a dismissible banner in the
|
||||
// sidebar (WhatsNewBanner) that links to the /whats-new page — no auto
|
||||
// modal takeover on startup.
|
||||
|
||||
@@ -1730,4 +1730,12 @@ export const deTranslation = {
|
||||
exitEndedBody: '„{{name}}" ist zu Ende. Hoffentlich war\'s schön.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Wiedergabe / Pause',
|
||||
nextTrack: 'Nächster Titel',
|
||||
previousTrack: 'Vorheriger Titel',
|
||||
showHide: 'Anzeigen / Verbergen',
|
||||
exitPsysonic: 'Psysonic beenden',
|
||||
nothingPlaying: 'Nichts wird abgespielt',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1737,4 +1737,12 @@ export const enTranslation = {
|
||||
exitEndedBody: '"{{name}}" has ended. Hope you had fun.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Play / Pause',
|
||||
nextTrack: 'Next Track',
|
||||
previousTrack: 'Previous Track',
|
||||
showHide: 'Show / Hide',
|
||||
exitPsysonic: 'Exit Psysonic',
|
||||
nothingPlaying: 'Nothing playing',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1717,4 +1717,12 @@ export const esTranslation = {
|
||||
exitEndedBody: '"{{name}}" ha terminado. Espero que te hayas divertido.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Reproducir / Pausa',
|
||||
nextTrack: 'Pista siguiente',
|
||||
previousTrack: 'Pista anterior',
|
||||
showHide: 'Mostrar / Ocultar',
|
||||
exitPsysonic: 'Salir de Psysonic',
|
||||
nothingPlaying: 'Nada en reproducción',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1712,4 +1712,12 @@ export const frTranslation = {
|
||||
exitEndedBody: '« {{name}} » est terminée. J\'espère que tu t\'es bien amusé.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Lecture / Pause',
|
||||
nextTrack: 'Piste suivante',
|
||||
previousTrack: 'Piste précédente',
|
||||
showHide: 'Afficher / Masquer',
|
||||
exitPsysonic: 'Quitter Psysonic',
|
||||
nothingPlaying: 'Aucune lecture',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1711,4 +1711,12 @@ export const nbTranslation = {
|
||||
exitEndedBody: '"{{name}}" er avsluttet. Håper du hadde det gøy.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Spill / Pause',
|
||||
nextTrack: 'Neste spor',
|
||||
previousTrack: 'Forrige spor',
|
||||
showHide: 'Vis / Skjul',
|
||||
exitPsysonic: 'Avslutt Psysonic',
|
||||
nothingPlaying: 'Ingenting spilles',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1711,4 +1711,12 @@ export const nlTranslation = {
|
||||
exitEndedBody: '"{{name}}" is beëindigd. Hopelijk had je plezier.',
|
||||
exitOk: 'OK',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Afspelen / Pauzeren',
|
||||
nextTrack: 'Volgende nummer',
|
||||
previousTrack: 'Vorige nummer',
|
||||
showHide: 'Tonen / Verbergen',
|
||||
exitPsysonic: 'Psysonic afsluiten',
|
||||
nothingPlaying: 'Niets wordt afgespeeld',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1798,4 +1798,12 @@ export const ruTranslation = {
|
||||
exitEndedBody: '«{{name}}» завершена. Надеюсь, тебе понравилось.',
|
||||
exitOk: 'ОК',
|
||||
},
|
||||
tray: {
|
||||
playPause: 'Воспроизвести / Пауза',
|
||||
nextTrack: 'Следующий трек',
|
||||
previousTrack: 'Предыдущий трек',
|
||||
showHide: 'Показать / Скрыть',
|
||||
exitPsysonic: 'Закрыть Psysonic',
|
||||
nothingPlaying: 'Ничего не воспроизводится',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1704,4 +1704,12 @@ export const zhTranslation = {
|
||||
exitEndedBody: '"{{name}}"已结束。希望你玩得开心。',
|
||||
exitOk: '好的',
|
||||
},
|
||||
tray: {
|
||||
playPause: '播放 / 暂停',
|
||||
nextTrack: '下一首',
|
||||
previousTrack: '上一首',
|
||||
showHide: '显示 / 隐藏',
|
||||
exitPsysonic: '退出 Psysonic',
|
||||
nothingPlaying: '当前没有播放',
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user