diff --git a/build-config/main/webpack.config.base.js b/build-config/main/webpack.config.base.js index 01a2d03d..fc5be7d5 100644 --- a/build-config/main/webpack.config.base.js +++ b/build-config/main/webpack.config.base.js @@ -9,6 +9,8 @@ module.exports = { }, resolve: { alias: { + '@': path.join(__dirname, '../../src/main'), + events: path.join(__dirname, '../../src/main/events'), common: path.join(__dirname, '../../src/common'), }, extensions: ['*', '.js', '.json', '.node'], diff --git a/package-lock.json b/package-lock.json index 0fa10792..00e4bbc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "lx-music-desktop", - "version": "0.16.0", + "version": "0.17.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/main/events/_name.js b/src/main/events/_name.js new file mode 100644 index 00000000..95d4d37c --- /dev/null +++ b/src/main/events/_name.js @@ -0,0 +1,5 @@ +exports.tray = { + create: 'create', + destroy: 'destroy', +} + diff --git a/src/main/events/index.js b/src/main/events/index.js index 0ad3cfed..15015415 100644 --- a/src/main/events/index.js +++ b/src/main/events/index.js @@ -1,13 +1,5 @@ +global.lx_event = {} -require('./request') -// require('./appName') -require('./progressBar') -require('./trafficLight') -require('./musicMeta') -require('./selectDir') -require('./setWindowSize') -require('./showSaveDialog') -require('./clearCache') -require('./getCacheSize') -require('./setIgnoreMouseEvent') -require('./getEnvParams') +const Tray = require('./tray') + +if (!global.lx_event.setting) global.lx_event.tray = new Tray() diff --git a/src/main/events/tray.js b/src/main/events/tray.js new file mode 100644 index 00000000..39867f43 --- /dev/null +++ b/src/main/events/tray.js @@ -0,0 +1,14 @@ +const { EventEmitter } = require('events') +const { tray: TRAY_EVENT_NAME } = require('./_name') + +class Tray extends EventEmitter { + create() { + this.emit(TRAY_EVENT_NAME.create) + } + + destroy() { + this.emit(TRAY_EVENT_NAME.destroy) + } +} + +module.exports = Tray diff --git a/src/main/index.js b/src/main/index.js index 33900686..f54798d4 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, Menu, Tray } = require('electron') +const { app, BrowserWindow } = require('electron') const path = require('path') // 单例应用程序 @@ -15,28 +15,28 @@ app.on('second-instance', (event, argv, cwd) => { } }) -const isDev = process.env.NODE_ENV !== 'production' +const isDev = global.isDev = process.env.NODE_ENV !== 'production' // https://github.com/electron/electron/issues/18397 app.allowRendererProcessReuse = !isDev -const { getWindowSizeInfo, parseEnv } = require('./utils') +const { getAppSetting, parseEnv, getWindowSizeInfo } = require('./utils') global.envParams = parseEnv() require('../common/error') require('./events') -const winEvent = require('./events/winEvent') +require('./rendererEvents') +const winEvent = require('./rendererEvents/winEvent') const autoUpdate = require('./utils/autoUpdate') -const { isLinux, isMac } = require('../common/utils') +const { isMac, isLinux } = require('../common/utils') let mainWindow let winURL -let isFirstCheckedUpdate = true -let tray if (isDev) { - global.__static = path.join(__dirname, '../static') + // eslint-disable-next-line no-undef + global.__static = __static winURL = 'http://localhost:9080' } else { global.__static = path.join(__dirname, '/static') @@ -44,7 +44,7 @@ if (isDev) { } function createWindow() { - let windowSizeInfo = getWindowSizeInfo() + const windowSizeInfo = getWindowSizeInfo(global.appSetting) /** * Initial window options */ @@ -66,87 +66,32 @@ function createWindow() { }, }) - // 托盘 - tray = new Tray( - isDev - ? 'src/static/512x512.png' - : path.join(global.__static, '512x512.png'), - ) - const contextMenu = Menu.buildFromTemplate([ - { - label: '退出', - click: () => { - mainWindow.destroy() - }, - }, - ]) - tray.setToolTip('洛雪音乐助手') - tray.setContextMenu(contextMenu) - tray.on('click', () => { - mainWindow.show() - mainWindow.setSkipTaskbar(false) - }) - mainWindow.loadURL(winURL) winEvent(mainWindow) // mainWindow.webContents.openDevTools() - if (!isDev) { - autoUpdate(isFirstCheckedUpdate) - isFirstCheckedUpdate = false - } + if (!isDev) autoUpdate() } -if (isMac) { - const template = [ - { - label: app.getName(), - submenu: [ - { label: '关于洛雪音乐', role: 'about' }, - { type: 'separator' }, - { label: '隐藏', role: 'hide' }, - { label: '显示其他', role: 'hideothers' }, - { label: '显示全部', role: 'unhide' }, - { type: 'separator' }, - { label: '退出', accelerator: 'Command+Q', click: () => app.quit() }, - ], - }, - { - label: '窗口', - role: 'window', - submenu: [ - { label: '最小化', role: 'minimize' }, - { label: '关闭', role: 'close' }, - ], - }, - { - label: '编辑', - submenu: [ - { label: '撤销', accelerator: 'CmdOrCtrl+Z', role: 'undo' }, - { label: '恢复', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' }, - { type: 'separator' }, - { label: '剪切', accelerator: 'CmdOrCtrl+X', role: 'cut' }, - { label: '复制', accelerator: 'CmdOrCtrl+C', role: 'copy' }, - { label: '粘贴', accelerator: 'CmdOrCtrl+V', role: 'paste' }, - { label: '选择全部', accelerator: 'CmdOrCtrl+A', role: 'selectAll' }, - ], - }, - ] - - Menu.setApplicationMenu(Menu.buildFromTemplate(template)) -} else { - Menu.setApplicationMenu(null) +function init() { + global.appSetting = getAppSetting() + createWindow() + global.lx_event.tray.create() } -app.on('ready', createWindow) - -app.on('window-all-closed', () => { - if (!isMac) app.quit() -}) +app.on('ready', init) app.on('activate', () => { - if (mainWindow === null) { - createWindow() + if (mainWindow === null) return init() +}) + +app.on('window-all-closed', () => { + if (isMac) { + global.lx_event.tray.destroy() + } else { + app.quit() } }) + +require('./modules') diff --git a/src/main/modules/appMenu.js b/src/main/modules/appMenu.js new file mode 100644 index 00000000..89bfd837 --- /dev/null +++ b/src/main/modules/appMenu.js @@ -0,0 +1,43 @@ +const { app, Menu } = require('electron') +const { isMac } = require('../../common/utils') + +if (isMac) { + const template = [ + { + label: app.getName(), + submenu: [ + { label: '关于洛雪音乐', role: 'about' }, + { type: 'separator' }, + { label: '隐藏', role: 'hide' }, + { label: '显示其他', role: 'hideothers' }, + { label: '显示全部', role: 'unhide' }, + { type: 'separator' }, + { label: '退出', accelerator: 'Command+Q', click: () => app.quit() }, + ], + }, + { + label: '窗口', + role: 'window', + submenu: [ + { label: '最小化', role: 'minimize' }, + { label: '关闭', role: 'close' }, + ], + }, + { + label: '编辑', + submenu: [ + { label: '撤销', accelerator: 'CmdOrCtrl+Z', role: 'undo' }, + { label: '恢复', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' }, + { type: 'separator' }, + { label: '剪切', accelerator: 'CmdOrCtrl+X', role: 'cut' }, + { label: '复制', accelerator: 'CmdOrCtrl+C', role: 'copy' }, + { label: '粘贴', accelerator: 'CmdOrCtrl+V', role: 'paste' }, + { label: '选择全部', accelerator: 'CmdOrCtrl+A', role: 'selectAll' }, + ], + }, + ] + + Menu.setApplicationMenu(Menu.buildFromTemplate(template)) +} else { + Menu.setApplicationMenu(null) +} diff --git a/src/main/modules/index.js b/src/main/modules/index.js new file mode 100644 index 00000000..bd79f0da --- /dev/null +++ b/src/main/modules/index.js @@ -0,0 +1,2 @@ +require('./appMenu') +require('./tray') diff --git a/src/main/modules/tray.js b/src/main/modules/tray.js new file mode 100644 index 00000000..5337c21c --- /dev/null +++ b/src/main/modules/tray.js @@ -0,0 +1,42 @@ +const { Tray, Menu } = require('electron') +const { isMac, isWin } = require('../../common/utils') +const { tray: TRAY_EVENT_NAME } = require('../events/_name') +const path = require('path') +global.lx_event.tray.on(TRAY_EVENT_NAME.create, () => { + createTray() +}) +global.lx_event.tray.on(TRAY_EVENT_NAME.destroy, () => { + destroyTray() +}) + +let tray +function createTray() { + if (tray && !tray.isDestroyed() && global.appSetting.tray && global.appSetting.tray.isShow) return + + const iconPath = path.join(global.__static, 'images/tray', isWin ? '256x256.ico' : isMac ? '512x512.icns' : '512x512.png') + + // 托盘 + tray = new Tray(iconPath) + + const contextMenu = Menu.buildFromTemplate([ + { + label: '退出', + role: 'quit', + }, + ]) + tray.setToolTip('洛雪音乐助手') + tray.setContextMenu(contextMenu) + tray.on('click', () => { + const mainWindow = global.mainWindow + if (!mainWindow) return + mainWindow.isVisible() + ? mainWindow.focus() + : mainWindow.show() + }) +} + +function destroyTray() { + if (!tray) return + tray.destroy() + tray = null +} diff --git a/src/main/events/appName.js b/src/main/rendererEvents/appName.js similarity index 100% rename from src/main/events/appName.js rename to src/main/rendererEvents/appName.js diff --git a/src/main/events/clearCache.js b/src/main/rendererEvents/clearCache.js similarity index 100% rename from src/main/events/clearCache.js rename to src/main/rendererEvents/clearCache.js diff --git a/src/main/events/getCacheSize.js b/src/main/rendererEvents/getCacheSize.js similarity index 100% rename from src/main/events/getCacheSize.js rename to src/main/rendererEvents/getCacheSize.js diff --git a/src/main/events/getEnvParams.js b/src/main/rendererEvents/getEnvParams.js similarity index 100% rename from src/main/events/getEnvParams.js rename to src/main/rendererEvents/getEnvParams.js diff --git a/src/main/rendererEvents/index.js b/src/main/rendererEvents/index.js new file mode 100644 index 00000000..a555a5bd --- /dev/null +++ b/src/main/rendererEvents/index.js @@ -0,0 +1,14 @@ + +require('./request') +// require('./appName') +require('./progressBar') +require('./trafficLight') +require('./musicMeta') +require('./selectDir') +require('./setWindowSize') +require('./showSaveDialog') +require('./clearCache') +require('./getCacheSize') +require('./setIgnoreMouseEvent') +require('./getEnvParams') +require('./tray') diff --git a/src/main/events/musicMeta.js b/src/main/rendererEvents/musicMeta.js similarity index 100% rename from src/main/events/musicMeta.js rename to src/main/rendererEvents/musicMeta.js diff --git a/src/main/events/progressBar.js b/src/main/rendererEvents/progressBar.js similarity index 100% rename from src/main/events/progressBar.js rename to src/main/rendererEvents/progressBar.js diff --git a/src/main/events/request.js b/src/main/rendererEvents/request.js similarity index 100% rename from src/main/events/request.js rename to src/main/rendererEvents/request.js diff --git a/src/main/events/restartWindow.js b/src/main/rendererEvents/restartWindow.js similarity index 100% rename from src/main/events/restartWindow.js rename to src/main/rendererEvents/restartWindow.js diff --git a/src/main/events/selectDir.js b/src/main/rendererEvents/selectDir.js similarity index 100% rename from src/main/events/selectDir.js rename to src/main/rendererEvents/selectDir.js diff --git a/src/main/events/setIgnoreMouseEvent.js b/src/main/rendererEvents/setIgnoreMouseEvent.js similarity index 100% rename from src/main/events/setIgnoreMouseEvent.js rename to src/main/rendererEvents/setIgnoreMouseEvent.js diff --git a/src/main/events/setWindowSize.js b/src/main/rendererEvents/setWindowSize.js similarity index 100% rename from src/main/events/setWindowSize.js rename to src/main/rendererEvents/setWindowSize.js diff --git a/src/main/events/showSaveDialog.js b/src/main/rendererEvents/showSaveDialog.js similarity index 100% rename from src/main/events/showSaveDialog.js rename to src/main/rendererEvents/showSaveDialog.js diff --git a/src/main/events/trafficLight.js b/src/main/rendererEvents/trafficLight.js similarity index 67% rename from src/main/events/trafficLight.js rename to src/main/rendererEvents/trafficLight.js index d0a7e046..d6e02b29 100644 --- a/src/main/events/trafficLight.js +++ b/src/main/rendererEvents/trafficLight.js @@ -11,14 +11,10 @@ mainOn('max', event => { global.mainWindow.maximize() } }) -mainOn('close', (event, arg) => { +mainOn('close', (event, params) => { if (global.mainWindow) { - console.log('close', arg) - if (arg && arg.min) { - global.mainWindow.hide() - global.mainWindow.setSkipTaskbar(true) - return - } + // console.log('close', params) + if (params && params.isToTray) return global.mainWindow.hide() // global.mainWindowdow.destroy() // app.quit() global.mainWindow.close() diff --git a/src/main/rendererEvents/tray.js b/src/main/rendererEvents/tray.js new file mode 100644 index 00000000..127abf4f --- /dev/null +++ b/src/main/rendererEvents/tray.js @@ -0,0 +1,17 @@ +// const { app } = require('electron') +const { mainOn } = require('../../common/ipc') + +mainOn('changeTray', (event, params) => { + switch (params.action) { + case 'create': + global.lx_event.tray.create() + break + case 'destroy': + global.lx_event.tray.destroy() + break + + default: + break + } +}) + diff --git a/src/main/events/winEvent.js b/src/main/rendererEvents/winEvent.js similarity index 100% rename from src/main/events/winEvent.js rename to src/main/rendererEvents/winEvent.js diff --git a/src/main/utils/autoUpdate.js b/src/main/utils/autoUpdate.js index 84ddd8d8..2e2cc857 100644 --- a/src/main/utils/autoUpdate.js +++ b/src/main/utils/autoUpdate.js @@ -5,6 +5,9 @@ const { mainOn } = require('../../common/ipc') autoUpdater.logger = log // autoUpdater.autoDownload = false autoUpdater.logger.transports.file.level = 'info' + +let isFirstCheckedUpdate = true + log.info('App starting...') @@ -67,7 +70,7 @@ const handleSendEvent = action => { } } -module.exports = isFirstCheckedUpdate => { +module.exports = () => { if (!isFirstCheckedUpdate) { if (waitEvent.length) { waitEvent.forEach((event, index) => { @@ -79,6 +82,8 @@ module.exports = isFirstCheckedUpdate => { } return } + isFirstCheckedUpdate = false + autoUpdater.on('checking-for-update', () => { sendStatusToWindow('Checking for update...') }) diff --git a/src/main/utils/index.js b/src/main/utils/index.js index 4f328a6a..cee08b53 100644 --- a/src/main/utils/index.js +++ b/src/main/utils/index.js @@ -1,12 +1,19 @@ const Store = require('electron-store') const { windowSizeList } = require('../../common/config') -exports.getWindowSizeInfo = () => { - let electronStore = new Store() - const { windowSizeId = 1 } = electronStore.get('setting') || {} +exports.getWindowSizeInfo = ({ windowSizeId = 1 } = {}) => { return windowSizeList.find(i => i.id === windowSizeId) || windowSizeList[0] } +exports.getAppSetting = () => { + let electronStore = new Store() + const defaultSetting = { + windowSizeId: 1, + isShowTray: false, + } + return Object.assign(defaultSetting, electronStore.get('setting') || {}) +} + exports.parseEnv = () => { const params = {} const rx = /^-\w+/ diff --git a/src/renderer/components/core/Toolbar.vue b/src/renderer/components/core/Toolbar.vue index b35d3987..15a3242f 100644 --- a/src/renderer/components/core/Toolbar.vue +++ b/src/renderer/components/core/Toolbar.vue @@ -120,7 +120,7 @@ export default { }, close() { rendererSend('close', { - min: this.setting.minClose, + isToTray: this.setting.tray.isToTray, }) }, }, diff --git a/src/renderer/lang/cns/view/setting.json b/src/renderer/lang/cns/view/setting.json index aa46ac8e..56c91698 100644 --- a/src/renderer/lang/cns/view/setting.json +++ b/src/renderer/lang/cns/view/setting.json @@ -18,8 +18,8 @@ "basic_window_size_medium": "中", "basic_window_size_big": "大", "basic_window_size_larger": "较大", - "basic_min_title": "关闭时最小化到系统托盘", - "basic_min": "关闭时最小化到系统托盘", + "basic_to_tray_title": "关闭时不退出软件将其最小化到系统托盘", + "basic_to_tray": "关闭时最小化到系统托盘", "basic_lang_title": "软件显示的语言", "basic_lang": "语言", diff --git a/src/renderer/lang/cnt/view/setting.json b/src/renderer/lang/cnt/view/setting.json index 50011d1c..5b52df1a 100644 --- a/src/renderer/lang/cnt/view/setting.json +++ b/src/renderer/lang/cnt/view/setting.json @@ -18,6 +18,8 @@ "basic_window_size_medium": "中", "basic_window_size_big": "大", "basic_window_size_larger": "較大", + "basic_to_tray_title": "關閉時不退出軟件將其最小化到系統托盤", + "basic_to_tray": "關閉時最小化到系統托盤", "basic_lang_title": "軟件顯示的語言", "basic_lang": "語言", "play": "播放設置", diff --git a/src/renderer/lang/en/view/setting.json b/src/renderer/lang/en/view/setting.json index 1ff617cd..e48a394d 100644 --- a/src/renderer/lang/en/view/setting.json +++ b/src/renderer/lang/en/view/setting.json @@ -18,6 +18,8 @@ "basic_window_size_medium": "medium", "basic_window_size_big": "big", "basic_window_size_larger": "Larger", + "basic_to_tray_title": "Minimize it to the system tray without closing the software when closing", + "basic_to_tray": "Minimize to system tray when closing", "basic_lang_title": "Software display language", "basic_lang": "Language", diff --git a/src/renderer/utils/index.js b/src/renderer/utils/index.js index 28e505c5..f69167e1 100644 --- a/src/renderer/utils/index.js +++ b/src/renderer/utils/index.js @@ -177,7 +177,7 @@ export const isChildren = (parent, children) => { * @param {*} setting */ export const updateSetting = (setting, version) => { - const defaultVersion = '1.0.19' + const defaultVersion = '1.0.22' if (!version) { if (setting) { version = setting.version @@ -238,6 +238,10 @@ export const updateSetting = (setting, version) => { password: '', }, }, + tray: { + isShow: false, + isToTray: false, + }, windowSizeId: 2, themeId: 0, minClose: false, diff --git a/src/renderer/views/Setting.vue b/src/renderer/views/Setting.vue index 4dce3714..1068926c 100644 --- a/src/renderer/views/Setting.vue +++ b/src/renderer/views/Setting.vue @@ -28,10 +28,10 @@ div.scroll(:class="$style.setting") material-checkbox(v-for="(item, index) in windowSizeList" :id="`setting_window_size_${item.id}`" name="setting_window_size" @change="handleWindowSizeChange" :class="$style.gapLeft" need v-model="current_setting.windowSizeId" :value="item.id" :label="$t('view.setting.basic_window_size_' + item.name)" :key="item.id") - dd(:title="$t('view.setting.basic_min_title')") - h3 {{$t('view.setting.basic_min')}} + dd(:title="$t('view.setting.basic_to_tray_title')") + h3 {{$t('view.setting.basic_to_tray')}} div - material-checkbox(id="setting_min" v-model="current_setting.minClose" :label="$t('view.setting.is_enable')") + material-checkbox(id="setting_to_tray" v-model="current_setting.tray.isToTray" @change="handleToTrayChange" :label="$t('view.setting.is_enable')") dd(:title="$t('view.setting.basic_lang_title')") h3 {{$t('view.setting.basic_lang')}} @@ -366,8 +366,11 @@ export default { themeId: 0, sourceId: 0, randomAnimate: true, - minClose: true, - apiSource: 'messoer', + tray: { + isShow: false, + isToTray: false, + }, + apiSource: 'temp', }, languageList, cacheSize: '0 B', @@ -618,6 +621,10 @@ export default { handleMediaDeviceChange(audioDevice) { this.setMediaDeviceId(audioDevice.deviceId) }, + handleToTrayChange(isToTray) { + this.current_setting.tray.isShow = isToTray + rendererSend('changeTray', { action: isToTray ? 'create' : 'destroy' }) + }, }, } diff --git a/src/static/images/tray/256x256.ico b/src/static/images/tray/256x256.ico new file mode 100644 index 00000000..a961683d Binary files /dev/null and b/src/static/images/tray/256x256.ico differ diff --git a/src/static/images/tray/512x512.icns b/src/static/images/tray/512x512.icns new file mode 100644 index 00000000..8bb1977e Binary files /dev/null and b/src/static/images/tray/512x512.icns differ diff --git a/src/static/512x512.png b/src/static/images/tray/512x512.png similarity index 100% rename from src/static/512x512.png rename to src/static/images/tray/512x512.png