Merge pull request #224 from Araxeus/menu-fixes

Menu tweaks
This commit is contained in:
th-ch
2021-05-04 21:24:29 +02:00
committed by GitHub
10 changed files with 263 additions and 187 deletions

View File

@ -98,10 +98,10 @@ function createMainWindow() {
affinity: "main-window", // main window, and addition windows should work in one process
...(isTesting()
? {
// Only necessary when testing with Spectron
contextIsolation: false,
nodeIntegration: true,
}
// Only necessary when testing with Spectron
contextIsolation: false,
nodeIntegration: true,
}
: undefined),
},
frame: !is.macOS() && !useInlineMenu,
@ -143,6 +143,10 @@ function createMainWindow() {
}
});
win.webContents.on("render-process-gone", (event, webContents, details) => {
showUnresponsiveDialog(win, details);
});
win.once("ready-to-show", () => {
if (config.get("options.appVisible")) {
win.show();
@ -152,14 +156,34 @@ function createMainWindow() {
return win;
}
app.on("browser-window-created", (event, win) => {
app.once("browser-window-created", (event, win) => {
loadPlugins(win);
win.webContents.on("did-fail-load", () => {
win.webContents.on("did-fail-load", (
_event,
errorCode,
errorDescription,
validatedURL,
isMainFrame,
frameProcessId,
frameRoutingId,
) => {
const log = JSON.stringify({
error: "did-fail-load",
errorCode,
errorDescription,
validatedURL,
isMainFrame,
frameProcessId,
frameRoutingId,
}, null, "\t");
if (is.dev()) {
console.log("did fail load");
console.log(log);
}
if( !(config.plugins.isEnabled("in-app-menu") && errorCode === -3)) { // -3 is a false positive with in-app-menu
win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
}
win.webContents.loadFile(path.join(__dirname, "error.html"));
});
win.webContents.on("will-prevent-unload", (event) => {
@ -279,13 +303,11 @@ app.on("ready", () => {
}
// Optimized for Mac OS X
if (is.macOS()) {
if (!config.get("options.appVisible")) {
app.dock.hide();
}
if (is.macOS() && !config.get("options.appVisible")) {
app.dock.hide();
}
var forceQuit = false;
let forceQuit = false;
app.on("before-quit", () => {
forceQuit = true;
});
@ -300,3 +322,27 @@ app.on("ready", () => {
});
}
});
function showUnresponsiveDialog(win, details) {
if (!!details) {
console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t"))
}
electron.dialog.showMessageBox(win, {
type: "error",
title: "Window Unresponsive",
message: "The Application is Unresponsive",
details: "We are sorry for the inconvenience! please choose what to do:",
buttons: ["Wait", "Relaunch", "Quit"],
cancelId: 0
}).then( result => {
switch (result.response) {
case 1: //if relaunch - relaunch+exit
app.relaunch();
case 2:
app.quit();
break;
default:
break;
}
});
}

236
menu.js
View File

@ -11,6 +11,8 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
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);
@ -23,18 +25,16 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
},
});
const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
const mainMenuTemplate = (win) => [
{
label: "Plugins",
submenu: [
...getAllPlugins().map((plugin) => {
const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js");
const pluginPath = path.join(__dirname, "plugins", plugin, "menu.js")
if (existsSync(pluginPath)) {
if (!config.plugins.isEnabled(plugin)) {
return pluginEnabledMenu(win, plugin, "", true);
}
const getPluginMenu = require(pluginPath);
return {
label: plugin,
@ -49,13 +49,6 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
return pluginEnabledMenu(win, plugin);
}),
{ type: "separator" },
{
label: "Advanced options",
click: () => {
config.edit();
},
},
],
},
{
@ -69,30 +62,6 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
config.set("options.autoUpdates", item.checked);
},
},
{
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);
},
},
{
label: "Resume last song when app starts",
type: "checkbox",
@ -103,29 +72,29 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
},
...(is.windows() || is.linux()
? [
{
label: "Hide menu",
type: "checkbox",
checked: config.get("options.hideMenu"),
click: (item) => {
config.set("options.hideMenu", item.checked);
},
{
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);
},
// 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",
@ -172,79 +141,96 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
},
{ type: "separator" },
{
label: "Toggle DevTools",
// Cannot use "toggleDevTools" role in MacOS
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: () => {
const { webContents } = win;
if (webContents.isDevToolsOpened()) {
webContents.closeDevTools();
} else {
const devToolsOptions = {};
webContents.openDevTools(devToolsOptions);
}
win.webContents.reload();
},
},
{
label: "Advanced options",
label: "Force Reload",
click: () => {
config.edit();
win.webContents.reloadIgnoringCache();
},
},
{ type: "separator" },
{
label: "Zoom In",
click: () => {
win.webContents.setZoomLevel(
win.webContents.getZoomLevel() + 1
);
},
},
{
label: "Zoom Out",
click: () => {
win.webContents.setZoomLevel(
win.webContents.getZoomLevel() - 1
);
},
},
{
label: "Reset Zoom",
click: () => {
win.webContents.setZoomLevel(0);
},
},
],
},
...(!isTray
? [
{
label: "View",
submenu: withRoles
? [
{ role: "reload" },
{ role: "forceReload" },
{ type: "separator" },
{ role: "zoomIn" },
{ role: "zoomOut" },
{ role: "resetZoom" },
]
: [
{
label: "Reload",
click: () => {
win.webContents.reload();
},
},
{
label: "Force Reload",
click: () => {
win.webContents.reloadIgnoringCache();
},
},
{ type: "separator" },
{
label: "Zoom In",
click: () => {
win.webContents.setZoomLevel(
win.webContents.getZoomLevel() + 1
);
},
},
{
label: "Zoom Out",
click: () => {
win.webContents.setZoomLevel(
win.webContents.getZoomLevel() - 1
);
},
},
{
label: "Reset Zoom",
click: () => {
win.webContents.setZoomLevel(0);
},
},
],
},
]
: []),
{
label: "Navigation",
submenu: [
@ -271,16 +257,12 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
app.quit();
},
},
...(!isTray
? [
{
label: "Quit App",
click: () => {
app.quit();
},
},
]
: []),
{
label: "Quit App",
click: () => {
app.quit();
},
},
],
},
];

View File

@ -102,6 +102,16 @@
"envs": [
"node",
"browser"
]
],
"rules": {
"quotes": [
"error",
"double",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
]
}
}
}

View File

@ -7,8 +7,8 @@ const config = require("../../config");
const { setApplicationMenu } = require("../../menu");
const { injectCSS } = require("../utils");
//check that menu doesn't get created twice
let done = false;
//tracks menu visibility
let visible = true;
// win hook for fixing menu
let win;
@ -16,7 +16,7 @@ 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
updateCheckboxesAndRadioButtons(win, template);
updateTemplate(template);
// return as normal
return originalBuildMenu(template);
@ -28,47 +28,54 @@ module.exports = (winImport) => {
// css for custom scrollbar + disable drag area(was causing bugs)
injectCSS(win.webContents, path.join(__dirname, "style.css"));
win.on("ready-to-show", () => {
// (apparently ready-to-show is called twice)
if (done) {
return;
}
done = true;
win.once("ready-to-show", () => {
setApplicationMenu(win);
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
switchMenuVisibility(win);
electronLocalshortcut.register(win, "Esc", () => {
switchMenuVisibility(win);
switchMenuVisibility();
});
}
});
//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"));
});
};
let visible = true;
function switchMenuVisibility(win) {
visible = !visible;
function switchMenuVisibility() {
setMenuVisibility(!visible);
}
function setMenuVisibility(value) {
visible = value;
win.webContents.send("updateMenu", visible);
}
function checkCheckbox(win, item) {
//check item
item.checked = !item.checked;
//update menu (closes it)
win.webContents.send("updateMenu", true);
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 updateCheckboxesAndRadioButtons(win, template) {
function updateTemplate(template) {
for (let item of template) {
// Change onClick of checkbox+radio
if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) {
let originalOnclick = item.click;
const originalOnclick = item.click;
item.click = (itemClicked) => {
originalOnclick(itemClicked);
checkCheckbox(win, itemClicked);
updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu);
};
item.fixed = true;
}

View File

@ -8,36 +8,46 @@
.menubar-menu-container {
overflow-y: visible !important;
}
/* fixes scrollbar positioning relative to nav bar */
#nav-bar-background.ytmusic-app-layout {
right: 15px !important;
}
/* remove window dragging for nav bar (conflict with titlebar drag) */
ytmusic-nav-bar,
.tab-titleiron-icon,
ytmusic-pivot-bar-item-renderer {
-webkit-app-region: unset;
}
/* Move navBar downwards and make it opaque */
ytmusic-app-layout {
--ytmusic-nav-bar-height: 120px;
}
ytmusic-search-box.ytmusic-nav-bar {
margin-top: 29px;
-webkit-app-region: unset !important;
}
/* navbar background black */
.center-content.ytmusic-nav-bar {
background: #030303;
}
yt-page-navigation-progress,
#progress.yt-page-navigation-progress,
ytmusic-item-section-renderer[has-item-section-tabbed-header-renderer_]
#header.ytmusic-item-section-renderer,
ytmusic-header-renderer.ytmusic-search-page {
top: 90px !important;
/* move up item selectrion renderer by 15 px */
ytmusic-item-section-renderer[has-item-section-tabbed-header-renderer_] #header.ytmusic-item-section-renderer {
top: 75 !important;
}
/* fix weird positioning in search screen*/
ytmusic-header-renderer.ytmusic-search-page {
position: unset !important;
}
/* Move navBar downwards */
ytmusic-app-layout > [slot="nav-bar"],
#nav-bar-background.ytmusic-app-layout {
top: 17px !important;
}
/* fix page progress bar position*/
yt-page-navigation-progress,
#progress.yt-page-navigation-progress {
top: 30px !important;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 12px;
@ -56,13 +66,13 @@ ytmusic-header-renderer.ytmusic-search-page {
background-clip: padding-box;
border: 2px solid rgba(0, 0, 0, 0);
background: rgb(49, 0, 0);
background: #3a3a3a;
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;
}
::-webkit-scrollbar-thumb:vertical:active {
background: rgb(56, 0, 0); /* Some darker color when you click it */
background: #4d4c4c; /* Some darker color when you click it */
border-radius: 100px;
-moz-border-radius: 100px;
-webkit-border-radius: 100px;

View File

@ -63,7 +63,7 @@ module.exports = (win) => {
const { playPause, next, previous, like, dislike } = getSongControls(win);
// If the page is ready, register the callback
win.on("ready-to-show", () => {
win.once("ready-to-show", () => {
controls = [previous, playPause, next, like, dislike];
// Register the callback

View File

@ -43,7 +43,7 @@ module.exports.fileExists = (path, callbackIfExists) => {
};
module.exports.injectCSS = (webContents, filepath, cb = undefined) => {
webContents.on("did-finish-load", async () => {
webContents.once("did-finish-load", async () => {
await webContents.insertCSS(fs.readFileSync(filepath, "utf8"));
if (cb) {
cb();

View File

@ -39,6 +39,9 @@ document.addEventListener("DOMContentLoaded", () => {
const songInfoProviderPath = path.join(__dirname, "providers", "song-info-front.js")
fileExists(songInfoProviderPath, require(songInfoProviderPath));
// inject front logger
require("./providers/front-logger")();
// Add action for reloading
global.reload = () =>
remote.getCurrentWindow().webContents.loadURL(config.get("url"));

13
providers/front-logger.js Normal file
View File

@ -0,0 +1,13 @@
const { ipcRenderer } = require("electron");
function logToString(log) {
return (typeof log === "string") ?
log :
JSON.stringify(log, null, "\t");
}
module.exports = () => {
ipcRenderer.on("log", (_event, log) => {
console.log(logToString(log));
});
};

View File

@ -3,7 +3,6 @@ const path = require("path");
const { Menu, nativeImage, Tray } = require("electron");
const config = require("./config");
const { mainMenuTemplate } = require("./menu");
const getSongControls = require("./providers/song-controls");
// Prevent tray being garbage collected
@ -57,7 +56,13 @@ module.exports.setUpTray = (app, win) => {
win.show();
},
},
...mainMenuTemplate(win, true, true),
{
label: "Restart App",
click: () => {
app.relaunch();
app.quit();
},
},
{
label: "Quit",
click: () => {