lx-music-desktop/src/main/modules/tray.ts
2024-03-17 19:32:31 +08:00

254 lines
6.5 KiB
TypeScript

import { Tray, Menu, nativeImage } from 'electron'
import { isWin } from '@common/utils'
import path from 'node:path'
import {
hideWindow as hideMainWindow,
isExistWindow as isExistMainWindow,
isShowWindow as isShowMainWindow,
sendEvent,
showWindow as showMainWindow,
} from './winMain'
import { quitApp } from '@main/app'
import { WIN_MAIN_RENDERER_EVENT_NAME } from '@common/ipcNames'
let tray: Electron.Tray | null
let isEnableTray: boolean = false
let themeId: number
const watchConfigKeys = [
'desktopLyric.enable',
'desktopLyric.isLock',
'desktopLyric.isAlwaysOnTop',
'tray.themeId',
'tray.enable',
'common.langId',
] satisfies Array<keyof LX.AppSetting>
const themeList = [
{
id: 0,
fileName: 'trayTemplate',
isNative: true,
},
{
id: 1,
fileName: 'tray_origin',
isNative: false,
},
{
id: 2,
fileName: 'tray_black',
isNative: false,
},
]
const messages = {
'en-us': {
hide_win_main: 'Hide Main Window',
show_win_main: 'Show Main Window',
hide_win_lyric: 'Close desktop lyrics',
show_win_lyric: 'Open desktop lyrics',
lock_win_lyric: 'Lock desktop lyrics',
unlock_win_lyric: 'Unlock desktop lyrics',
top_win_lyric: 'Set top lyrics',
untop_win_lyric: 'Cancel top lyrics',
exit: 'Exit',
},
'zh-cn': {
hide_win_main: '隐藏主界面',
show_win_main: '显示主界面',
hide_win_lyric: '关闭桌面歌词',
show_win_lyric: '开启桌面歌词',
lock_win_lyric: '锁定桌面歌词',
unlock_win_lyric: '解锁桌面歌词',
top_win_lyric: '置顶歌词',
untop_win_lyric: '取消置顶',
exit: '退出',
},
'zh-tw': {
hide_win_main: '隱藏主界面',
show_win_main: '顯示主界面',
hide_win_lyric: '關閉桌面歌詞',
show_win_lyric: '開啟桌面歌詞',
lock_win_lyric: '鎖定桌面歌詞',
unlock_win_lyric: '解鎖桌面歌詞',
top_win_lyric: '置頂歌詞',
untop_win_lyric: '取消置頂',
exit: '退出',
},
} as const
type Messages = typeof messages
type Langs = keyof Messages
const i18n = {
message: messages['zh-cn'] as Messages[Langs],
fallbackLocale: 'en-us' as 'en-us',
getMessage(key: keyof Messages[Langs]) {
return this.message[key]
},
setLang(lang?: Langs | null) {
this.message = lang
? messages[lang] ?? messages[this.fallbackLocale]
: messages[this.fallbackLocale]
},
}
export const createTray = () => {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if ((tray && !tray.isDestroyed()) || !global.lx.appSetting['tray.enable']) return
themeId = global.lx.appSetting['tray.themeId']
let theme = themeList.find(item => item.id === themeId) ?? themeList[0]
const iconPath = path.join(global.staticPath, 'images/tray', theme.fileName + '.png')
// 托盘
tray = new Tray(nativeImage.createFromPath(iconPath))
tray.setToolTip('LX Music')
createMenu()
tray.setIgnoreDoubleClickEvents(true)
tray.on('click', () => {
showMainWindow()
})
}
export const destroyTray = () => {
if (!tray) return
tray.destroy()
isEnableTray = false
tray = null
}
const handleUpdateConfig = (config: any) => {
global.lx.event_app.update_config(config)
}
export const createMenu = () => {
if (!tray) return
let menu = []
if (isExistMainWindow()) {
const isShow = isShowMainWindow()
menu.push(isShow
? {
label: i18n.getMessage('hide_win_main'),
click() {
hideMainWindow()
},
}
: {
label: i18n.getMessage('show_win_main'),
click() {
showMainWindow()
},
})
menu.push({
label: '设置',
click() {
sendEvent(WIN_MAIN_RENDERER_EVENT_NAME.on_open_setting)
showMainWindow()
},
})
}
menu.push(global.lx.appSetting['desktopLyric.enable']
? {
label: i18n.getMessage('hide_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.enable': false })
},
}
: {
label: i18n.getMessage('show_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.enable': true })
},
})
menu.push(global.lx.appSetting['desktopLyric.isLock']
? {
label: i18n.getMessage('unlock_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.isLock': false })
},
}
: {
label: i18n.getMessage('lock_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.isLock': true })
},
})
menu.push(global.lx.appSetting['desktopLyric.isAlwaysOnTop']
? {
label: i18n.getMessage('untop_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.isAlwaysOnTop': false })
},
}
: {
label: i18n.getMessage('top_win_lyric'),
click() {
handleUpdateConfig({ 'desktopLyric.isAlwaysOnTop': true })
},
})
menu.push({
label: i18n.getMessage('exit'),
click() {
quitApp()
},
})
const contextMenu = Menu.buildFromTemplate(menu)
tray.setContextMenu(contextMenu)
}
export const setTrayImage = (themeId: number) => {
if (!tray) return
let theme = themeList.find(item => item.id === themeId) ?? themeList[0]
const iconPath = path.join(global.staticPath, 'images/tray', theme.fileName + '.png')
tray.setImage(nativeImage.createFromPath(iconPath))
}
const init = () => {
if (themeId != global.lx.appSetting['tray.themeId']) {
themeId = global.lx.appSetting['tray.themeId']
setTrayImage(themeId)
}
if (isEnableTray !== global.lx.appSetting['tray.enable']) {
isEnableTray = global.lx.appSetting['tray.enable']
global.lx.appSetting['tray.enable'] ? createTray() : destroyTray()
}
createMenu()
}
export default () => {
global.lx.event_app.on('updated_config', (keys, setting) => {
if (!watchConfigKeys.some(key => keys.includes(key))) return
if (keys.includes('common.langId')) i18n.setLang(setting['common.langId'])
init()
})
global.lx.event_app.on('main_window_ready_to_show', () => {
createMenu()
})
global.lx.event_app.on('main_window_show', () => {
createMenu()
})
if (!isWin) {
global.lx.event_app.on('main_window_focus', () => {
createMenu()
})
global.lx.event_app.on('main_window_blur', () => {
createMenu()
})
}
global.lx.event_app.on('main_window_hide', () => {
createMenu()
})
global.lx.event_app.on('main_window_close', () => {
destroyTray()
})
global.lx.event_app.on('app_inited', () => {
i18n.setLang(global.lx.appSetting['common.langId'])
init()
})
}