diff --git a/menu.js b/menu.js index 957d2b2b..72b2cc66 100644 --- a/menu.js +++ b/menu.js @@ -7,12 +7,13 @@ const is = require("electron-is"); const { getAllPlugins } = require("./plugins/utils"); const config = require("./config"); -const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ +// true only if in-app-menu was loaded on launch +const inAppMenuActive = config.plugins.isEnabled("in-app-menu"); + +const pluginEnabledMenu = (plugin, label = "", hasSubmenu = false, refreshMenu = undefined) => ({ label: label || plugin, type: "checkbox", checked: config.plugins.isEnabled(plugin), - //Submenu check used in in-app-menu - hasSubmenu: hasSubmenu || undefined, click: (item) => { if (item.checked) { config.plugins.enable(plugin); @@ -20,252 +21,226 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({ config.plugins.disable(plugin); } if (hasSubmenu) { - this.setApplicationMenu(win); + refreshMenu(); } }, }); -const mainMenuTemplate = (win) => [ - { - label: "Plugins", - submenu: [ - ...getAllPlugins().map((plugin) => { - const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js") - if (existsSync(pluginPath)) { - if (!config.plugins.isEnabled(plugin)) { - return pluginEnabledMenu(win, plugin, "", true); +const mainMenuTemplate = (win) => { + const refreshMenu = () => { + this.setApplicationMenu(win); + if (inAppMenuActive) { + win.webContents.send("updateMenu", true); + } + } + return [ + { + label: "Plugins", + submenu: [ + ...getAllPlugins().map((plugin) => { + const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js") + if (existsSync(pluginPath)) { + if (!config.plugins.isEnabled(plugin)) { + return pluginEnabledMenu(plugin, "", true, refreshMenu); + } + const getPluginMenu = require(pluginPath); + return { + label: plugin, + submenu: [ + pluginEnabledMenu(plugin, "Enabled", true, refreshMenu), + ...getPluginMenu(win, config.plugins.getOptions(plugin), refreshMenu), + ], + }; } - const getPluginMenu = require(pluginPath); - return { - label: plugin, - submenu: [ - pluginEnabledMenu(win, plugin, "Enabled", true), - ...getPluginMenu(win, config.plugins.getOptions(plugin), () => - module.exports.setApplicationMenu(win) - ), - ], - }; - } - return pluginEnabledMenu(win, plugin); - }), - ], - }, - { - label: "Options", - submenu: [ - { - label: "Auto-update", - type: "checkbox", - checked: config.get("options.autoUpdates"), - click: (item) => { - config.set("options.autoUpdates", item.checked); - }, - }, - { - label: "Resume last song when app starts", - type: "checkbox", - checked: config.get("options.resumeOnStart"), - click: (item) => { - config.set("options.resumeOnStart", item.checked); - }, - }, - ...(is.windows() || is.linux() - ? [ - { - label: "Hide menu", - type: "checkbox", - checked: config.get("options.hideMenu"), - click: (item) => { - config.set("options.hideMenu", item.checked); - }, + return pluginEnabledMenu(plugin); + }), + ], + }, + { + label: "Options", + submenu: [ + { + label: "Auto-update", + type: "checkbox", + checked: config.get("options.autoUpdates"), + click: (item) => { + config.set("options.autoUpdates", item.checked); }, - ] - : []), - ...(is.windows() || is.macOS() - ? // Only works on Win/Mac - // https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows - [ - { - label: "Start at login", - type: "checkbox", - checked: config.get("options.startAtLogin"), - click: (item) => { - config.set("options.startAtLogin", item.checked); - }, - }, - ] - : []), - { - label: "Tray", - submenu: [ - { - label: "Disabled", - type: "radio", - checked: !config.get("options.tray"), - click: () => { - config.set("options.tray", false); - config.set("options.appVisible", true); - }, - }, - { - label: "Enabled + app visible", - type: "radio", - checked: - config.get("options.tray") && config.get("options.appVisible"), - click: () => { - config.set("options.tray", true); - config.set("options.appVisible", true); - }, - }, - { - label: "Enabled + app hidden", - type: "radio", - checked: - config.get("options.tray") && !config.get("options.appVisible"), - click: () => { - config.set("options.tray", true); - config.set("options.appVisible", false); - }, - }, - { type: "separator" }, - { - label: "Play/Pause on click", - type: "checkbox", - checked: config.get("options.trayClickPlayPause"), - click: (item) => { - config.set("options.trayClickPlayPause", item.checked); - }, - }, - ], - }, - { type: "separator" }, - { - label: "Advanced options", - submenu: [ - { - label: "Disable hardware acceleration", - type: "checkbox", - checked: config.get("options.disableHardwareAcceleration"), - click: (item) => { - config.set("options.disableHardwareAcceleration", item.checked); - }, - }, - { - label: "Restart on config changes", - type: "checkbox", - checked: config.get("options.restartOnConfigChanges"), - click: (item) => { - config.set("options.restartOnConfigChanges", item.checked); - }, - }, - { - label: "Reset App cache when app starts", - type: "checkbox", - checked: config.get("options.autoResetAppCache"), - click: (item) => { - config.set("options.autoResetAppCache", item.checked); - }, - }, - { type: "separator" }, - { - label: "Toggle DevTools", - // Cannot use "toggleDevTools" role in MacOS - click: () => { - const { webContents } = win; - if (webContents.isDevToolsOpened()) { - webContents.closeDevTools(); - } else { - const devToolsOptions = {}; - webContents.openDevTools(devToolsOptions); - } - }, - }, - { - label: "Edit config.json", - click: () => { - config.edit(); - }, - }, - ] - }, - ], - }, - { - label: "View", - submenu: [ - { - label: "Reload", - click: () => { - win.webContents.reload(); }, - }, - { - label: "Force Reload", - click: () => { - win.webContents.reloadIgnoringCache(); + { + label: "Resume last song when app starts", + type: "checkbox", + checked: config.get("options.resumeOnStart"), + click: (item) => { + config.set("options.resumeOnStart", item.checked); + }, }, - }, - { type: "separator" }, - { - label: "Zoom In", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() + 1 - ); + ...(is.windows() || is.linux() + ? [ + { + label: "Hide menu", + type: "checkbox", + checked: config.get("options.hideMenu"), + click: (item) => { + config.set("options.hideMenu", item.checked); + }, + }, + ] + : []), + ...(is.windows() || is.macOS() + ? // Only works on Win/Mac + // https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows + [ + { + label: "Start at login", + type: "checkbox", + checked: config.get("options.startAtLogin"), + click: (item) => { + config.set("options.startAtLogin", item.checked); + }, + }, + ] + : []), + { + label: "Tray", + submenu: [ + { + label: "Disabled", + type: "radio", + checked: !config.get("options.tray"), + click: () => { + config.set("options.tray", false); + config.set("options.appVisible", true); + }, + }, + { + label: "Enabled + app visible", + type: "radio", + checked: + config.get("options.tray") && config.get("options.appVisible"), + click: () => { + config.set("options.tray", true); + config.set("options.appVisible", true); + }, + }, + { + label: "Enabled + app hidden", + type: "radio", + checked: + config.get("options.tray") && !config.get("options.appVisible"), + click: () => { + config.set("options.tray", true); + config.set("options.appVisible", false); + }, + }, + { type: "separator" }, + { + label: "Play/Pause on click", + type: "checkbox", + checked: config.get("options.trayClickPlayPause"), + click: (item) => { + config.set("options.trayClickPlayPause", item.checked); + }, + }, + ], }, - }, - { - label: "Zoom Out", - click: () => { - win.webContents.setZoomLevel( - win.webContents.getZoomLevel() - 1 - ); + { type: "separator" }, + { + label: "Advanced options", + submenu: [ + { + label: "Disable hardware acceleration", + type: "checkbox", + checked: config.get("options.disableHardwareAcceleration"), + click: (item) => { + config.set("options.disableHardwareAcceleration", item.checked); + }, + }, + { + label: "Restart on config changes", + type: "checkbox", + checked: config.get("options.restartOnConfigChanges"), + click: (item) => { + config.set("options.restartOnConfigChanges", item.checked); + }, + }, + { + label: "Reset App cache when app starts", + type: "checkbox", + checked: config.get("options.autoResetAppCache"), + click: (item) => { + config.set("options.autoResetAppCache", item.checked); + }, + }, + { type: "separator" }, + is.macOS() ? + { + label: "Toggle DevTools", + // Cannot use "toggleDevTools" role in MacOS + click: () => { + const { webContents } = win; + if (webContents.isDevToolsOpened()) { + webContents.closeDevTools(); + } else { + const devToolsOptions = {}; + webContents.openDevTools(devToolsOptions); + } + }, + } : + { role: "toggleDevTools" }, + { + label: "Edit config.json", + click: () => { + config.edit(); + }, + }, + ] }, - }, - { - label: "Reset Zoom", - click: () => { - win.webContents.setZoomLevel(0); + ], + }, + { + label: "View", + submenu: [ + { role: "reload" }, + { role: "forceReload" }, + { type: "separator" }, + { role: "zoomIn" }, + { role: "zoomOut" }, + { role: "resetZoom" }, + ], + }, + { + label: "Navigation", + submenu: [ + { + label: "Go back", + click: () => { + if (win.webContents.canGoBack()) { + win.webContents.goBack(); + } + }, }, - }, - ], - }, - { - label: "Navigation", - submenu: [ - { - label: "Go back", - click: () => { - if (win.webContents.canGoBack()) { - win.webContents.goBack(); - } + { + label: "Go forward", + click: () => { + if (win.webContents.canGoForward()) { + win.webContents.goForward(); + } + }, }, - }, - { - label: "Go forward", - click: () => { - if (win.webContents.canGoForward()) { - win.webContents.goForward(); - } + { + label: "Restart App", + click: () => { + app.relaunch(); + app.quit(); + }, }, - }, - { - label: "Restart App", - click: () => { - app.relaunch(); - app.quit(); - }, - }, - { - label: "Quit App", - click: () => { - app.quit(); - }, - }, - ], - }, -]; + { role: "quit" }, + ], + }, + ]; +} module.exports.mainMenuTemplate = mainMenuTemplate; module.exports.setApplicationMenu = (win) => { diff --git a/package.json b/package.json index 9e331d29..f28ce402 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,8 @@ "YoutubeNonStop": "git://github.com/lawfx/YoutubeNonStop.git#v0.9.0", "async-mutex": "^0.3.1", "browser-id3-writer": "^4.4.0", - "chokidar": "^3.5.1", "custom-electron-titlebar": "^3.2.7", + "chokidar": "^3.5.1", "discord-rpc": "^3.2.0", "electron-debug": "^3.2.0", "electron-is": "^3.0.0", diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js index 82b0af4f..9624bb77 100644 --- a/plugins/in-app-menu/back.js +++ b/plugins/in-app-menu/back.js @@ -1,83 +1,33 @@ const path = require("path"); -const { Menu } = require("electron"); const electronLocalshortcut = require("electron-localshortcut"); const config = require("../../config"); -const { setApplicationMenu } = require("../../menu"); const { injectCSS } = require("../utils"); //tracks menu visibility let visible = true; -// win hook for fixing menu -let win; - -const originalBuildMenu = Menu.buildFromTemplate; -// This function natively gets called on all submenu so no more reason to use recursion -Menu.buildFromTemplate = (template) => { - // Fix checkboxes and radio buttons - updateTemplate(template); - - // return as normal - return originalBuildMenu(template); -}; - -module.exports = (winImport) => { - win = winImport; +module.exports = (win) => { // css for custom scrollbar + disable drag area(was causing bugs) injectCSS(win.webContents, path.join(__dirname, "style.css")); win.once("ready-to-show", () => { - - setApplicationMenu(win); - //register keyboard shortcut && hide menu if hideMenu is enabled if (config.get("options.hideMenu")) { electronLocalshortcut.register(win, "Esc", () => { - switchMenuVisibility(); + setMenuVisibility(!visible); }); } }); - //set menu visibility on load win.webContents.once("did-finish-load", () => { // fix bug with menu not applying on start when no internet connection available setMenuVisibility(!config.get("options.hideMenu")); }); + + function setMenuVisibility(value) { + visible = value; + win.webContents.send("updateMenu", visible); + } }; - -function switchMenuVisibility() { - setMenuVisibility(!visible); -} - -function setMenuVisibility(value) { - visible = value; - win.webContents.send("updateMenu", visible); -} - -function updateCheckboxesAndRadioButtons(item, isRadio, hasSubmenu) { - if (!isRadio) { - //fix checkbox - item.checked = !item.checked; - } - //update menu if radio / hasSubmenu - if (isRadio || hasSubmenu) { - win.webContents.send("updateMenu", true); - } -} - -// Update checkboxes/radio buttons -function updateTemplate(template) { - for (let item of template) { - // Change onClick of checkbox+radio - if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { - const originalOnclick = item.click; - item.click = (itemClicked) => { - originalOnclick(itemClicked); - updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu); - }; - item.fixed = true; - } - } -} diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js index 3287dc5d..49e56b2b 100644 --- a/plugins/in-app-menu/front.js +++ b/plugins/in-app-menu/front.js @@ -10,15 +10,7 @@ module.exports = () => { bar.updateTitle(" "); document.title = "Youtube Music"; - ipcRenderer.on("updateMenu", function (event, menu) { - if (menu) { - bar.updateMenu(remote.Menu.getApplicationMenu()); - } else { - try { - bar.updateMenu(null); - } catch (e) { - //will always throw type error - null isn't menu, but it works - } - } + ipcRenderer.on("updateMenu", function (_event, showMenu) { + bar.updateMenu(showMenu ? remote.Menu.getApplicationMenu() : null); }); }; diff --git a/plugins/in-app-menu/style.css b/plugins/in-app-menu/style.css index c6339093..d1efb3d0 100644 --- a/plugins/in-app-menu/style.css +++ b/plugins/in-app-menu/style.css @@ -4,11 +4,6 @@ font-size: 14px !important; } -/* allow submenu's to show correctly */ -.menubar-menu-container { - overflow-y: visible !important; -} - /* fixes scrollbar positioning relative to nav bar */ #nav-bar-background.ytmusic-app-layout { right: 15px !important; diff --git a/tray.js b/tray.js index 7d0331f7..b89902ab 100644 --- a/tray.js +++ b/tray.js @@ -63,12 +63,7 @@ module.exports.setUpTray = (app, win) => { app.quit(); }, }, - { - label: "Quit", - click: () => { - app.quit(); - }, - }, + { role: "quit" } ]; const trayMenu = Menu.buildFromTemplate(template);