mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 23:57:22 +08:00
Binary file not shown.
|
After Width: | Height: | Size: 269 B |
Binary file not shown.
|
After Width: | Height: | Size: 141 B |
Binary file not shown.
|
After Width: | Height: | Size: 251 B |
Binary file not shown.
|
After Width: | Height: | Size: 289 B |
@@ -41,7 +41,12 @@ export default {
|
|||||||
songCount: '{count} songs',
|
songCount: '{count} songs',
|
||||||
tray: {
|
tray: {
|
||||||
show: 'Show',
|
show: 'Show',
|
||||||
quit: 'Quit'
|
quit: 'Quit',
|
||||||
|
playPause: 'Play/Pause',
|
||||||
|
prev: 'Previous',
|
||||||
|
next: 'Next',
|
||||||
|
pause: 'Pause',
|
||||||
|
play: 'Play'
|
||||||
},
|
},
|
||||||
language: 'Language'
|
language: 'Language'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ export default {
|
|||||||
language: '语言',
|
language: '语言',
|
||||||
tray: {
|
tray: {
|
||||||
show: '显示',
|
show: '显示',
|
||||||
quit: '退出'
|
quit: '退出',
|
||||||
|
playPause: '播放/暂停',
|
||||||
|
prev: '上一首',
|
||||||
|
next: '下一首',
|
||||||
|
pause: '暂停',
|
||||||
|
play: '播放'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+12
-2
@@ -9,7 +9,7 @@ import { initializeConfig } from './modules/config';
|
|||||||
import { initializeFileManager } from './modules/fileManager';
|
import { initializeFileManager } from './modules/fileManager';
|
||||||
import { initializeFonts } from './modules/fonts';
|
import { initializeFonts } from './modules/fonts';
|
||||||
import { initializeShortcuts, registerShortcuts } from './modules/shortcuts';
|
import { initializeShortcuts, registerShortcuts } from './modules/shortcuts';
|
||||||
import { initializeTray, updateTrayMenu } from './modules/tray';
|
import { initializeTray, updateCurrentSong, updatePlayState, updateTrayMenu } from './modules/tray';
|
||||||
import { setupUpdateHandlers } from './modules/update';
|
import { setupUpdateHandlers } from './modules/update';
|
||||||
import { createMainWindow, initializeWindowManager } from './modules/window';
|
import { createMainWindow, initializeWindowManager } from './modules/window';
|
||||||
import { startMusicApi } from './server';
|
import { startMusicApi } from './server';
|
||||||
@@ -109,11 +109,21 @@ if (!isSingleInstance) {
|
|||||||
// 更新主进程的语言设置
|
// 更新主进程的语言设置
|
||||||
i18n.global.locale = locale;
|
i18n.global.locale = locale;
|
||||||
// 更新托盘菜单
|
// 更新托盘菜单
|
||||||
updateTrayMenu();
|
updateTrayMenu(mainWindow);
|
||||||
// 通知所有窗口语言已更改
|
// 通知所有窗口语言已更改
|
||||||
mainWindow?.webContents.send('language-changed', locale);
|
mainWindow?.webContents.send('language-changed', locale);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听播放状态变化
|
||||||
|
ipcMain.on('update-play-state', (_, playing: boolean) => {
|
||||||
|
updatePlayState(playing);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听当前歌曲变化
|
||||||
|
ipcMain.on('update-current-song', (_, song: any) => {
|
||||||
|
updateCurrentSong(song);
|
||||||
|
});
|
||||||
|
|
||||||
// 所有窗口关闭时的处理
|
// 所有窗口关闭时的处理
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
|
|||||||
+382
-46
@@ -1,82 +1,418 @@
|
|||||||
import { app, BrowserWindow, Menu, nativeImage, Tray } from 'electron';
|
import {
|
||||||
|
app,
|
||||||
|
BrowserWindow,
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
MenuItemConstructorOptions,
|
||||||
|
nativeImage,
|
||||||
|
Tray
|
||||||
|
} from 'electron';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import type { Language } from '../../i18n/main';
|
import type { Language } from '../../i18n/main';
|
||||||
import i18n from '../../i18n/main';
|
import i18n from '../../i18n/main';
|
||||||
|
|
||||||
|
// 歌曲信息接口定义
|
||||||
|
interface SongInfo {
|
||||||
|
name: string;
|
||||||
|
song: {
|
||||||
|
artists: Array<{ name: string; [key: string]: any }>;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
let tray: Tray | null = null;
|
let tray: Tray | null = null;
|
||||||
|
// 为macOS状态栏添加控制图标
|
||||||
|
let playPauseTray: Tray | null = null;
|
||||||
|
let prevTray: Tray | null = null;
|
||||||
|
let nextTray: Tray | null = null;
|
||||||
|
let songTitleTray: Tray | null = null;
|
||||||
|
|
||||||
|
let isPlaying = false;
|
||||||
|
let currentSong: SongInfo | null = null;
|
||||||
|
|
||||||
const LANGUAGES: { label: string; value: Language }[] = [
|
const LANGUAGES: { label: string; value: Language }[] = [
|
||||||
{ label: '简体中文', value: 'zh-CN' },
|
{ label: '简体中文', value: 'zh-CN' },
|
||||||
{ label: 'English', value: 'en-US' }
|
{ label: 'English', value: 'en-US' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 更新播放状态
|
||||||
|
export function updatePlayState(playing: boolean) {
|
||||||
|
isPlaying = playing;
|
||||||
|
if (tray) {
|
||||||
|
updateTrayMenu(BrowserWindow.getAllWindows()[0]);
|
||||||
|
}
|
||||||
|
// 更新播放/暂停图标
|
||||||
|
updateStatusBarTray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取艺术家名称字符串
|
||||||
|
function getArtistString(song: SongInfo | null): string {
|
||||||
|
if (!song || !song.song || !song.song.artists) return '';
|
||||||
|
return song.song.artists.map((item) => item.name).join(' / ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取歌曲完整标题(歌曲名 - 艺术家)
|
||||||
|
function getSongTitle(song: SongInfo | null): string {
|
||||||
|
if (!song) return '未播放';
|
||||||
|
const artistStr = getArtistString(song);
|
||||||
|
return artistStr ? `${song.name} - ${artistStr}` : song.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新当前播放的音乐信息
|
||||||
|
export function updateCurrentSong(song: SongInfo | null) {
|
||||||
|
currentSong = song;
|
||||||
|
if (tray) {
|
||||||
|
updateTrayMenu(BrowserWindow.getAllWindows()[0]);
|
||||||
|
}
|
||||||
|
// 更新状态栏歌曲信息
|
||||||
|
updateStatusBarTray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保 macOS 状态栏图标能正确显示
|
||||||
|
function getProperIconSize() {
|
||||||
|
// macOS 状态栏通常高度为22像素
|
||||||
|
const height = 18;
|
||||||
|
const width = 18;
|
||||||
|
return { width, height };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新macOS状态栏图标
|
||||||
|
function updateStatusBarTray() {
|
||||||
|
if (process.platform !== 'darwin') return;
|
||||||
|
|
||||||
|
const iconSize = getProperIconSize();
|
||||||
|
|
||||||
|
// 更新歌曲标题显示
|
||||||
|
if (songTitleTray) {
|
||||||
|
if (currentSong) {
|
||||||
|
// 限制歌曲名显示长度,添加作者名
|
||||||
|
const songName = currentSong.name.slice(0, 10);
|
||||||
|
let title = songName;
|
||||||
|
const artistStr = getArtistString(currentSong);
|
||||||
|
// 如果有艺术家名称,添加到标题中
|
||||||
|
if (artistStr) {
|
||||||
|
title = `${songName} - ${artistStr.slice(0, 6)}${artistStr.length > 6 ? '..' : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置标题和提示
|
||||||
|
songTitleTray.setTitle(title, {
|
||||||
|
fontType: 'monospacedDigit' // 使用等宽字体以确保更好的可读性
|
||||||
|
});
|
||||||
|
|
||||||
|
// 完整信息放在tooltip中
|
||||||
|
const fullTitle = getSongTitle(currentSong);
|
||||||
|
songTitleTray.setToolTip(fullTitle);
|
||||||
|
console.log('更新状态栏歌曲显示:', title, '完整信息:', fullTitle);
|
||||||
|
} else {
|
||||||
|
songTitleTray.setTitle('未播放', {
|
||||||
|
fontType: 'monospacedDigit'
|
||||||
|
});
|
||||||
|
songTitleTray.setToolTip('未播放');
|
||||||
|
console.log('更新状态栏歌曲显示: 未播放');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新播放/暂停图标
|
||||||
|
if (playPauseTray) {
|
||||||
|
// 使用PNG图标替代文本
|
||||||
|
const iconPath = join(
|
||||||
|
app.getAppPath(),
|
||||||
|
'resources/icons',
|
||||||
|
isPlaying ? 'pause.png' : 'play.png'
|
||||||
|
);
|
||||||
|
const icon = nativeImage.createFromPath(iconPath).resize(iconSize);
|
||||||
|
icon.setTemplateImage(true); // 设置为模板图片,适合macOS深色/浅色模式
|
||||||
|
playPauseTray.setImage(icon);
|
||||||
|
playPauseTray.setToolTip(
|
||||||
|
isPlaying ? i18n.global.t('common.tray.pause') : i18n.global.t('common.tray.play')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 导出更新菜单的函数
|
// 导出更新菜单的函数
|
||||||
export function updateTrayMenu() {
|
export function updateTrayMenu(mainWindow: BrowserWindow) {
|
||||||
if (!tray) return;
|
if (!tray) return;
|
||||||
|
|
||||||
// 创建一个上下文菜单
|
// 如果是macOS,设置TouchBar
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
if (process.platform === 'darwin') {
|
||||||
{
|
// macOS 上使用直接的控制按钮
|
||||||
label: i18n.global.t('common.tray.show'),
|
const menu = new Menu();
|
||||||
click: () => {
|
|
||||||
BrowserWindow.getAllWindows()[0]?.show();
|
// 当前播放的音乐信息
|
||||||
}
|
if (currentSong) {
|
||||||
},
|
menu.append(
|
||||||
{ type: 'separator' },
|
new MenuItem({
|
||||||
{
|
label: getSongTitle(currentSong),
|
||||||
label: i18n.global.t('common.language'),
|
enabled: false,
|
||||||
submenu: LANGUAGES.map(({ label, value }) => ({
|
type: 'normal'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
menu.append(new MenuItem({ type: 'separator' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上一首、播放/暂停、下一首的菜单项
|
||||||
|
// 在macOS上临时使用文本菜单项替代图标,确保基本功能正常
|
||||||
|
menu.append(
|
||||||
|
new MenuItem({
|
||||||
|
label: i18n.global.t('common.tray.prev'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'prevPlay');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
menu.append(
|
||||||
|
new MenuItem({
|
||||||
|
label: i18n.global.t(isPlaying ? 'common.tray.pause' : 'common.tray.play'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'togglePlay');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
menu.append(
|
||||||
|
new MenuItem({
|
||||||
|
label: i18n.global.t('common.tray.next'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'nextPlay');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 分隔符
|
||||||
|
menu.append(new MenuItem({ type: 'separator' }));
|
||||||
|
|
||||||
|
// 显示主窗口
|
||||||
|
menu.append(
|
||||||
|
new MenuItem({
|
||||||
|
label: i18n.global.t('common.tray.show'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 语言切换子菜单
|
||||||
|
const languageSubmenu = Menu.buildFromTemplate(
|
||||||
|
LANGUAGES.map(({ label, value }) => ({
|
||||||
label,
|
label,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
checked: i18n.global.locale === value,
|
checked: i18n.global.locale === value,
|
||||||
click: () => {
|
click: () => {
|
||||||
// 更新主进程的语言设置
|
|
||||||
i18n.global.locale = value;
|
i18n.global.locale = value;
|
||||||
// 更新托盘菜单
|
updateTrayMenu(mainWindow);
|
||||||
updateTrayMenu();
|
mainWindow.webContents.send('language-changed', value);
|
||||||
// 直接通知主窗口
|
|
||||||
const windows = BrowserWindow.getAllWindows();
|
|
||||||
for (const win of windows) {
|
|
||||||
win.webContents.send('language-changed', value);
|
|
||||||
console.log('向窗口发送语言变更事件:', value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
},
|
);
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: i18n.global.t('common.tray.quit'),
|
|
||||||
click: () => {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 设置系统托盘图标的上下文菜单
|
menu.append(
|
||||||
tray.setContextMenu(contextMenu);
|
new MenuItem({
|
||||||
|
label: i18n.global.t('common.language'),
|
||||||
|
type: 'submenu',
|
||||||
|
submenu: languageSubmenu
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// 退出按钮
|
||||||
|
menu.append(
|
||||||
|
new MenuItem({
|
||||||
|
label: i18n.global.t('common.tray.quit'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
tray.setContextMenu(menu);
|
||||||
|
} else {
|
||||||
|
// Windows 和 Linux 使用原来的菜单样式
|
||||||
|
const menuTemplate: MenuItemConstructorOptions[] = [
|
||||||
|
// 当前播放的音乐信息
|
||||||
|
...((currentSong
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
label: getSongTitle(currentSong),
|
||||||
|
enabled: false,
|
||||||
|
type: 'normal'
|
||||||
|
},
|
||||||
|
{ type: 'separator' }
|
||||||
|
]
|
||||||
|
: []) as MenuItemConstructorOptions[]),
|
||||||
|
{
|
||||||
|
label: i18n.global.t('common.tray.show'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
|
{
|
||||||
|
label: i18n.global.t('common.tray.prev'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'prevPlay');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t(isPlaying ? 'common.tray.pause' : 'common.tray.play'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'togglePlay');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t('common.tray.next'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'nextPlay');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
|
{
|
||||||
|
label: i18n.global.t('common.language'),
|
||||||
|
type: 'submenu',
|
||||||
|
submenu: LANGUAGES.map(({ label, value }) => ({
|
||||||
|
label,
|
||||||
|
type: 'radio',
|
||||||
|
checked: i18n.global.locale === value,
|
||||||
|
click: () => {
|
||||||
|
i18n.global.locale = value;
|
||||||
|
updateTrayMenu(mainWindow);
|
||||||
|
mainWindow.webContents.send('language-changed', value);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
|
{
|
||||||
|
label: i18n.global.t('common.tray.quit'),
|
||||||
|
type: 'normal',
|
||||||
|
click: () => {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const contextMenu = Menu.buildFromTemplate(menuTemplate);
|
||||||
|
tray.setContextMenu(contextMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化状态栏Tray
|
||||||
|
function initializeStatusBarTray(mainWindow: BrowserWindow) {
|
||||||
|
if (process.platform !== 'darwin') return;
|
||||||
|
|
||||||
|
const iconSize = getProperIconSize();
|
||||||
|
|
||||||
|
// 创建下一首按钮(调整顺序,先创建下一首按钮)
|
||||||
|
const nextIcon = nativeImage
|
||||||
|
.createFromPath(join(app.getAppPath(), 'resources/icons', 'next.png'))
|
||||||
|
.resize(iconSize);
|
||||||
|
nextIcon.setTemplateImage(true); // 设置为模板图片,适合macOS深色/浅色模式
|
||||||
|
nextTray = new Tray(nextIcon);
|
||||||
|
nextTray.setToolTip(i18n.global.t('common.tray.next'));
|
||||||
|
nextTray.on('click', () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'nextPlay');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建播放/暂停按钮
|
||||||
|
const playPauseIcon = nativeImage
|
||||||
|
.createFromPath(join(app.getAppPath(), 'resources/icons', isPlaying ? 'pause.png' : 'play.png'))
|
||||||
|
.resize(iconSize);
|
||||||
|
playPauseIcon.setTemplateImage(true); // 设置为模板图片,适合macOS深色/浅色模式
|
||||||
|
playPauseTray = new Tray(playPauseIcon);
|
||||||
|
playPauseTray.setToolTip(
|
||||||
|
isPlaying ? i18n.global.t('common.tray.pause') : i18n.global.t('common.tray.play')
|
||||||
|
);
|
||||||
|
playPauseTray.on('click', () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'togglePlay');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建上一首按钮(调整顺序,最后创建上一首按钮)
|
||||||
|
const prevIcon = nativeImage
|
||||||
|
.createFromPath(join(app.getAppPath(), 'resources/icons', 'prev.png'))
|
||||||
|
.resize(iconSize);
|
||||||
|
prevIcon.setTemplateImage(true); // 设置为模板图片,适合macOS深色/浅色模式
|
||||||
|
prevTray = new Tray(prevIcon);
|
||||||
|
prevTray.setToolTip(i18n.global.t('common.tray.prev'));
|
||||||
|
prevTray.on('click', () => {
|
||||||
|
mainWindow.webContents.send('global-shortcut', 'prevPlay');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建歌曲信息显示 - 需要使用特殊处理
|
||||||
|
const titleIcon = nativeImage
|
||||||
|
.createFromPath(join(app.getAppPath(), 'resources/icons', 'note.png'))
|
||||||
|
.resize({ width: 16, height: 16 });
|
||||||
|
titleIcon.setTemplateImage(true);
|
||||||
|
songTitleTray = new Tray(titleIcon);
|
||||||
|
|
||||||
|
// 初始化显示文本
|
||||||
|
const initialText = getSongTitle(currentSong);
|
||||||
|
|
||||||
|
// 在macOS上,特别设置title来显示文本,确保它能正确显示
|
||||||
|
songTitleTray.setTitle(initialText, {
|
||||||
|
fontType: 'monospacedDigit' // 使用等宽字体以确保更好的可读性
|
||||||
|
});
|
||||||
|
|
||||||
|
songTitleTray.setToolTip(initialText);
|
||||||
|
songTitleTray.on('click', () => {
|
||||||
|
mainWindow.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 强制更新一次所有图标
|
||||||
|
updateStatusBarTray();
|
||||||
|
|
||||||
|
// 打印调试信息
|
||||||
|
console.log('状态栏初始化完成,歌曲显示标题:', initialText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化系统托盘
|
* 初始化系统托盘
|
||||||
*/
|
*/
|
||||||
export function initializeTray(iconPath: string, mainWindow: BrowserWindow) {
|
export function initializeTray(iconPath: string, mainWindow: BrowserWindow) {
|
||||||
|
// 根据平台选择合适的图标
|
||||||
|
const iconSize = process.platform === 'darwin' ? 18 : 16;
|
||||||
|
const iconFile = process.platform === 'darwin' ? 'icon_16x16.png' : 'icon_16x16.png';
|
||||||
|
|
||||||
const trayIcon = nativeImage
|
const trayIcon = nativeImage
|
||||||
.createFromPath(join(iconPath, 'icon_16x16.png'))
|
.createFromPath(join(iconPath, iconFile))
|
||||||
.resize({ width: 16, height: 16 });
|
.resize({ width: iconSize, height: iconSize });
|
||||||
|
|
||||||
tray = new Tray(trayIcon);
|
tray = new Tray(trayIcon);
|
||||||
|
|
||||||
// 初始化菜单
|
// 设置托盘图标的提示文字
|
||||||
updateTrayMenu();
|
tray.setToolTip('Alger Music Player');
|
||||||
|
|
||||||
// 当系统托盘图标被点击时,切换窗口的显示/隐藏
|
// 初始化菜单
|
||||||
tray.on('click', () => {
|
updateTrayMenu(mainWindow);
|
||||||
if (mainWindow.isVisible()) {
|
|
||||||
mainWindow.hide();
|
// 初始化状态栏控制按钮 (macOS)
|
||||||
} else {
|
initializeStatusBarTray(mainWindow);
|
||||||
mainWindow.show();
|
|
||||||
}
|
// 在 macOS 上,点击图标时显示菜单
|
||||||
});
|
if (process.platform === 'darwin') {
|
||||||
|
tray.on('click', () => {
|
||||||
|
if (tray) {
|
||||||
|
tray.popUpContextMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 在其他平台上,点击图标时切换窗口显示状态
|
||||||
|
tray.on('click', () => {
|
||||||
|
if (mainWindow.isVisible()) {
|
||||||
|
mainWindow.hide();
|
||||||
|
} else {
|
||||||
|
mainWindow.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return tray;
|
return tray;
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -20,6 +20,7 @@ declare global {
|
|||||||
removeDownloadListeners: () => void;
|
removeDownloadListeners: () => void;
|
||||||
onLanguageChanged: (callback: (locale: string) => void) => void;
|
onLanguageChanged: (callback: (locale: string) => void) => void;
|
||||||
invoke: (channel: string, ...args: any[]) => Promise<any>;
|
invoke: (channel: string, ...args: any[]) => Promise<any>;
|
||||||
|
sendSong: (data: any) => void;
|
||||||
};
|
};
|
||||||
$message: any;
|
$message: any;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const api = {
|
|||||||
restart: () => ipcRenderer.send('restart'),
|
restart: () => ipcRenderer.send('restart'),
|
||||||
openLyric: () => ipcRenderer.send('open-lyric'),
|
openLyric: () => ipcRenderer.send('open-lyric'),
|
||||||
sendLyric: (data) => ipcRenderer.send('send-lyric', data),
|
sendLyric: (data) => ipcRenderer.send('send-lyric', data),
|
||||||
|
sendSong: (data) => ipcRenderer.send('update-current-song', data),
|
||||||
unblockMusic: (id) => ipcRenderer.invoke('unblock-music', id),
|
unblockMusic: (id) => ipcRenderer.invoke('unblock-music', id),
|
||||||
// 歌词窗口关闭事件
|
// 歌词窗口关闭事件
|
||||||
onLyricWindowClosed: (callback: () => void) => {
|
onLyricWindowClosed: (callback: () => void) => {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
import { darkTheme, lightTheme } from 'naive-ui';
|
import { darkTheme, lightTheme } from 'naive-ui';
|
||||||
import { computed, nextTick, watch } from 'vue';
|
import { computed, nextTick, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
@@ -90,6 +91,7 @@ onMounted(async () => {
|
|||||||
// 使用 nextTick 确保 DOM 更新后再初始化
|
// 使用 nextTick 确保 DOM 更新后再初始化
|
||||||
await nextTick();
|
await nextTick();
|
||||||
initAudioListeners();
|
initAudioListeners();
|
||||||
|
window.api.sendSong(cloneDeep(playerStore.playMusic));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { cloneDeep } from 'lodash';
|
||||||
import { createDiscreteApi } from 'naive-ui';
|
import { createDiscreteApi } from 'naive-ui';
|
||||||
import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
|
import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
@@ -394,6 +395,7 @@ const setupAudioListeners = () => {
|
|||||||
// 监听播放
|
// 监听播放
|
||||||
audioService.on('play', () => {
|
audioService.on('play', () => {
|
||||||
playerStore.setPlayMusic(true);
|
playerStore.setPlayMusic(true);
|
||||||
|
window.api.sendSong(cloneDeep(playerStore.playMusic));
|
||||||
clearInterval();
|
clearInterval();
|
||||||
interval = window.setInterval(() => {
|
interval = window.setInterval(() => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -353,14 +353,15 @@ export const usePlayerStore = defineStore('player', () => {
|
|||||||
|
|
||||||
const setIsPlay = (value: boolean) => {
|
const setIsPlay = (value: boolean) => {
|
||||||
isPlay.value = value;
|
isPlay.value = value;
|
||||||
|
play.value = value;
|
||||||
localStorage.setItem('isPlaying', value.toString());
|
localStorage.setItem('isPlaying', value.toString());
|
||||||
|
// 通知主进程播放状态变化
|
||||||
|
window.electron?.ipcRenderer.send('update-play-state', value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setPlayMusic = async (value: boolean | SongResult) => {
|
const setPlayMusic = async (value: boolean | SongResult) => {
|
||||||
if (typeof value === 'boolean') {
|
if (typeof value === 'boolean') {
|
||||||
play.value = value;
|
setIsPlay(value);
|
||||||
isPlay.value = value;
|
|
||||||
localStorage.setItem('isPlaying', value.toString());
|
|
||||||
} else {
|
} else {
|
||||||
await handlePlayMusic(value);
|
await handlePlayMusic(value);
|
||||||
play.value = true;
|
play.value = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user