From 216205200c68c1168b2bfcd256f973ac258a65e3 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 15:30:33 +0300
Subject: [PATCH 01/52] fix in-app-menu navbar opacity + scrollbar color
---
plugins/in-app-menu/style.css | 40 +++++++++++++++++------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/plugins/in-app-menu/style.css b/plugins/in-app-menu/style.css
index 25ae7c4a..19dd59fb 100644
--- a/plugins/in-app-menu/style.css
+++ b/plugins/in-app-menu/style.css
@@ -8,36 +8,36 @@
.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;
+ -webkit-app-region: unset !important;
}
-/* Move navBar downwards and make it opaque */
-ytmusic-app-layout {
- --ytmusic-nav-bar-height: 120px;
-}
-
-ytmusic-search-box.ytmusic-nav-bar {
- margin-top: 29px;
-}
-
-.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,
+/* fix weird positioning in search screen*/
ytmusic-header-renderer.ytmusic-search-page {
- top: 90px !important;
+ 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 +56,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;
From 2b3a20c5ffd438eeb6b144ed1ca8c55316b83d36 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 15:47:32 +0300
Subject: [PATCH 02/52] Minimalize tray menu -doesnt include main menu template
anymore
---
menu.js | 134 ++++++++++++++++++++++++++------------------------------
tray.js | 9 +++-
2 files changed, 69 insertions(+), 74 deletions(-)
diff --git a/menu.js b/menu.js
index f974c4e4..e41fd9e0 100644
--- a/menu.js
+++ b/menu.js
@@ -23,18 +23,16 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
},
});
-const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
+const mainMenuTemplate = (win, withRoles = true) => [
{
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,
@@ -46,7 +44,7 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
],
};
}
-
+
return pluginEnabledMenu(win, plugin);
}),
{ type: "separator" },
@@ -111,12 +109,12 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
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
- [
+ // https://www.electronjs.org/docs/api/app#appsetloginitemsettingssettings-macos-windows
+ [
{
label: "Start at login",
type: "checkbox",
@@ -125,7 +123,7 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
config.set("options.startAtLogin", item.checked);
},
},
- ]
+ ]
: []),
{
label: "Tray",
@@ -192,59 +190,55 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
},
],
},
- ...(!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: "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 +265,12 @@ const mainMenuTemplate = (win, withRoles = true, isTray = false) => [
app.quit();
},
},
- ...(!isTray
- ? [
- {
- label: "Quit App",
- click: () => {
- app.quit();
- },
- },
- ]
- : []),
+ {
+ label: "Quit App",
+ click: () => {
+ app.quit();
+ },
+ },
],
},
];
diff --git a/tray.js b/tray.js
index e871f4bf..7d0331f7 100644
--- a/tray.js
+++ b/tray.js
@@ -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: () => {
From 80a7d2c255d3238adaf4e712de35194fd2633853 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 15:54:51 +0300
Subject: [PATCH 03/52] remove redundant roles
---
menu.js | 115 +++++++++++++++++-------------------
plugins/in-app-menu/back.js | 14 ++---
2 files changed, 60 insertions(+), 69 deletions(-)
diff --git a/menu.js b/menu.js
index e41fd9e0..893ae015 100644
--- a/menu.js
+++ b/menu.js
@@ -23,7 +23,7 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
},
});
-const mainMenuTemplate = (win, withRoles = true) => [
+const mainMenuTemplate = (win) => [
{
label: "Plugins",
submenu: [
@@ -44,7 +44,7 @@ const mainMenuTemplate = (win, withRoles = true) => [
],
};
}
-
+
return pluginEnabledMenu(win, plugin);
}),
{ type: "separator" },
@@ -101,28 +101,28 @@ const mainMenuTemplate = (win, withRoles = true) => [
},
...(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);
- },
+ {
+ label: "Start at login",
+ type: "checkbox",
+ checked: config.get("options.startAtLogin"),
+ click: (item) => {
+ config.set("options.startAtLogin", item.checked);
},
+ },
]
: []),
{
@@ -192,52 +192,43 @@ const mainMenuTemplate = (win, withRoles = true) => [
},
{
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);
- },
- },
- ],
+ submenu: [
+ {
+ 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",
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 3c77c377..f5925815 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -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);
+ updateCheckboxesAndRadioButtons(template);
// return as normal
return originalBuildMenu(template);
@@ -39,21 +39,21 @@ module.exports = (winImport) => {
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
- switchMenuVisibility(win);
+ switchMenuVisibility();
electronLocalshortcut.register(win, "Esc", () => {
- switchMenuVisibility(win);
+ switchMenuVisibility();
});
}
});
};
let visible = true;
-function switchMenuVisibility(win) {
+function switchMenuVisibility() {
visible = !visible;
win.webContents.send("updateMenu", visible);
}
-function checkCheckbox(win, item) {
+function checkCheckbox(item) {
//check item
item.checked = !item.checked;
//update menu (closes it)
@@ -61,14 +61,14 @@ function checkCheckbox(win, item) {
}
// Update checkboxes/radio buttons
-function updateCheckboxesAndRadioButtons(win, template) {
+function updateCheckboxesAndRadioButtons(template) {
for (let item of template) {
// Change onClick of checkbox+radio
if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) {
let originalOnclick = item.click;
item.click = (itemClicked) => {
originalOnclick(itemClicked);
- checkCheckbox(win, itemClicked);
+ checkCheckbox(itemClicked);
};
item.fixed = true;
}
From 5524a14c871ccf47a2f4237468eb5cdc0c678b21 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 19:20:56 +0300
Subject: [PATCH 04/52] move advanced options to dedicated submenu + add "Use
Proxy" checkbox
---
menu.js | 102 ++++++++++++++++++++++++++++++--------------------------
1 file changed, 55 insertions(+), 47 deletions(-)
diff --git a/menu.js b/menu.js
index 893ae015..c0843247 100644
--- a/menu.js
+++ b/menu.js
@@ -47,13 +47,6 @@ const mainMenuTemplate = (win) => [
return pluginEnabledMenu(win, plugin);
}),
- { type: "separator" },
- {
- label: "Advanced options",
- click: () => {
- config.edit();
- },
- },
],
},
{
@@ -67,30 +60,6 @@ const mainMenuTemplate = (win) => [
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",
@@ -169,24 +138,63 @@ const mainMenuTemplate = (win) => [
],
},
{ 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: "Advanced options",
- click: () => {
- config.edit();
- },
+ submenu: [
+ {
+ label: "Use Proxy",
+ type: "checkbox",
+ checked: !!config.get("options.proxy"),
+ click: (item) => {
+ const value = item.checked? "socks5://127.0.0.1:9999" : "";
+ config.set("options.proxy", value);
+ }
+ },
+ {
+ 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();
+ },
+ },
+ ]
},
],
},
From ec3adff70676f2b9f5fe94f7bd0ed670f6373bb4 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 20:15:48 +0300
Subject: [PATCH 05/52] fix bug when loading window with no connection
---
plugins/in-app-menu/back.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index f5925815..c8660ecb 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -36,6 +36,8 @@ module.exports = (winImport) => {
done = true;
setApplicationMenu(win);
+ //fix bug when loading window with no internet connection
+ switchMenuVisibility();
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
@@ -47,7 +49,7 @@ module.exports = (winImport) => {
});
};
-let visible = true;
+let visible = false;
function switchMenuVisibility() {
visible = !visible;
win.webContents.send("updateMenu", visible);
From 061e4a9e5f0e8d6743f933df14aefa6685bbb8ed Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 21:51:35 +0300
Subject: [PATCH 06/52] add 'electron-prompt' and use it for setting proxy
---
menu.js | 36 +++++++++++++++++++++++++++++++++---
package.json | 1 +
yarn.lock | 19 +++++++++++++++++++
3 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/menu.js b/menu.js
index c0843247..3c6efa86 100644
--- a/menu.js
+++ b/menu.js
@@ -6,11 +6,13 @@ const is = require("electron-is");
const { getAllPlugins } = require("./plugins/utils");
const config = require("./config");
+const prompt = require('electron-prompt');
const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
label: label || plugin,
type: "checkbox",
checked: config.plugins.isEnabled(plugin),
+ hasSubmenu: hasSubmenu || undefined,
click: (item) => {
if (item.checked) {
config.plugins.enable(plugin);
@@ -142,12 +144,12 @@ const mainMenuTemplate = (win) => [
label: "Advanced options",
submenu: [
{
- label: "Use Proxy",
+ label: "Proxy",
type: "checkbox",
checked: !!config.get("options.proxy"),
+ //fixed: true, //skip in-app-menu click() override
click: (item) => {
- const value = item.checked? "socks5://127.0.0.1:9999" : "";
- config.set("options.proxy", value);
+ setProxy(item, win);
}
},
{
@@ -307,3 +309,31 @@ module.exports.setApplicationMenu = (win) => {
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
};
+
+//
+const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
+function setProxy(item, win) {
+ prompt({
+ title: 'Set Proxy',
+ label: 'Enter Proxy Adress:',
+ value: config.get("options.proxy") || `Example - "socks5://127.0.0.1:9999"`,
+ inputAttrs: {
+ type: 'text'
+ },
+ type: 'input',
+ alwaysOnTop: true,
+ icon: iconPath
+ })
+ .then((input) => {
+ if(input !== null) {
+ console.log(`setting proxy to ${input}`);
+ config.set("options.proxy", input);
+ if(input === "")
+ item.checked = false;
+ item.checked = (input === "") ? false : true;
+ } else { //user pressed cancel
+ item.checked = !item.checked; //reset checkbox
+ }
+ })
+ .catch(console.error);
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index ce144c38..736374c5 100644
--- a/package.json
+++ b/package.json
@@ -74,6 +74,7 @@
"electron-debug": "^3.2.0",
"electron-is": "^3.0.0",
"electron-localshortcut": "^3.2.1",
+ "electron-prompt": "^1.6.2",
"electron-store": "^7.0.2",
"electron-unhandled": "^3.0.2",
"electron-updater": "^4.3.6",
diff --git a/yarn.lock b/yarn.lock
index c969527e..b029d432 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2908,6 +2908,13 @@ dmg-builder@22.9.1:
js-yaml "^3.14.0"
sanitize-filename "^1.6.3"
+doc-ready@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/doc-ready/-/doc-ready-1.0.4.tgz#37f5391969cff994303fdfef2e5d50357f8164d3"
+ integrity sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM=
+ dependencies:
+ eventie "^1"
+
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@@ -3086,6 +3093,13 @@ electron-localshortcut@^3.1.0, electron-localshortcut@^3.2.1:
keyboardevent-from-electron-accelerator "^2.0.0"
keyboardevents-areequal "^0.2.1"
+electron-prompt@^1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/electron-prompt/-/electron-prompt-1.6.2.tgz#e26bd3d359120bd45ce2f9625bdc380deb7ee269"
+ integrity sha512-gC9ZpMopIgz1kW92J7UfsXarkLdPH2zhr77bnJFlDSduYjRlr9nEPm4ux1vyzJsO72AdOyvuPPIQB0j+gWsncQ==
+ dependencies:
+ doc-ready "^1.0.4"
+
electron-publish@22.9.1:
version "22.9.1"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.9.1.tgz#7cc76ac4cc53efd29ee31c1e5facb9724329068e"
@@ -3605,6 +3619,11 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+eventie@^1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/eventie/-/eventie-1.0.6.tgz#d4ffc8b0c2b5e493c2aa1b22cbe918d3aee74437"
+ integrity sha1-1P/IsMK15JPCqhsiy+kY067nRDc=
+
events@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
From 317521bba618dadb20304596766a360a9b897462 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 21:53:39 +0300
Subject: [PATCH 07/52] fix memory leak + in-app-menu updates menu only if
needed
---
index.js | 6 ++++++
plugins/in-app-menu/back.js | 16 ++++++++++------
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/index.js b/index.js
index 82bb3320..478d2f86 100644
--- a/index.js
+++ b/index.js
@@ -152,7 +152,13 @@ function createMainWindow() {
return win;
}
+let createdWindow = false;
app.on("browser-window-created", (event, win) => {
+ //Ensure listeners aren't registered when creating input dialog
+ if(createdWindow){
+ return;
+ }
+ createdWindow = true;
loadPlugins(win);
win.webContents.on("did-fail-load", () => {
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index c8660ecb..fba6eb6d 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -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(template);
+ updateTemplate(template);
// return as normal
return originalBuildMenu(template);
@@ -55,22 +55,26 @@ function switchMenuVisibility() {
win.webContents.send("updateMenu", visible);
}
-function checkCheckbox(item) {
- //check item
+function updateCheckboxesAndRadioButtons(item, isRadio, hasSubmenu) {
+ if (!isRadio) {
+ //fix checkbox
item.checked = !item.checked;
- //update menu (closes it)
+ }
+ //update menu if radio / hasSubmenu
+ if (isRadio || hasSubmenu) {
win.webContents.send("updateMenu", true);
+ }
}
// Update checkboxes/radio buttons
-function updateCheckboxesAndRadioButtons(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;
item.click = (itemClicked) => {
originalOnclick(itemClicked);
- checkCheckbox(itemClicked);
+ updateCheckboxesAndRadioButtons(itemClicked, item.type==='radio', item.hasSubmenu);
};
item.fixed = true;
}
From 70b03b71e4bfa45df6cb70130bf896dd0ec8d755 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 22:04:40 +0300
Subject: [PATCH 08/52] refactor and stylecheck
---
menu.js | 3 ---
plugins/in-app-menu/back.js | 13 ++++++++++---
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/menu.js b/menu.js
index 3c6efa86..b51fb516 100644
--- a/menu.js
+++ b/menu.js
@@ -147,7 +147,6 @@ const mainMenuTemplate = (win) => [
label: "Proxy",
type: "checkbox",
checked: !!config.get("options.proxy"),
- //fixed: true, //skip in-app-menu click() override
click: (item) => {
setProxy(item, win);
}
@@ -310,7 +309,6 @@ module.exports.setApplicationMenu = (win) => {
Menu.setApplicationMenu(menu);
};
-//
const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
function setProxy(item, win) {
prompt({
@@ -326,7 +324,6 @@ function setProxy(item, win) {
})
.then((input) => {
if(input !== null) {
- console.log(`setting proxy to ${input}`);
config.set("options.proxy", input);
if(input === "")
item.checked = false;
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index fba6eb6d..8a6efdf7 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -9,6 +9,8 @@ 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;
@@ -41,17 +43,22 @@ module.exports = (winImport) => {
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
- switchMenuVisibility();
+ visible = false;
electronLocalshortcut.register(win, "Esc", () => {
switchMenuVisibility();
});
}
+ // fix bug with menu not applying on start
+ setMenuVisibility(visible);
});
};
-let visible = false;
function switchMenuVisibility() {
- visible = !visible;
+ setMenuVisibility(!visible);
+}
+
+function setMenuVisibility(value){
+ visible = value;
win.webContents.send("updateMenu", visible);
}
From 1cae35a62b5c4aa687eb66cd9449cb3351947498 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 22:34:12 +0300
Subject: [PATCH 09/52] fix in-app-menu hideMenu on launch
---
plugins/in-app-menu/back.js | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 8a6efdf7..53bb9f8d 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -38,17 +38,15 @@ module.exports = (winImport) => {
done = true;
setApplicationMenu(win);
- //fix bug when loading window with no internet connection
- switchMenuVisibility();
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
- visible = false;
+ switchMenuVisibility();
electronLocalshortcut.register(win, "Esc", () => {
switchMenuVisibility();
});
- }
- // fix bug with menu not applying on start
+ }
+ // fix bug with menu not applying on start when no internet connection available
setMenuVisibility(visible);
});
};
From 8b6c60bb178e3bc22c8c917f650153a960ea9ae6 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 22:59:20 +0300
Subject: [PATCH 10/52] fix Connection Error when using in-app-menu
---
index.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/index.js b/index.js
index 478d2f86..bc3db73a 100644
--- a/index.js
+++ b/index.js
@@ -93,6 +93,7 @@ function createMainWindow() {
contextIsolation: false,
preload: path.join(__dirname, "preload.js"),
nodeIntegrationInSubFrames: true,
+ nodeIntegration: true,
nativeWindowOpen: true, // window.open return Window object(like in regular browsers), not BrowserWindowProxy
enableRemoteModule: true,
affinity: "main-window", // main window, and addition windows should work in one process
From 2e6fffc903953b2f4cd6c5321f36f22677572d37 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sat, 3 Apr 2021 23:46:16 +0300
Subject: [PATCH 11/52] Revert "fix Connection Error when using in-app-menu"
This reverts commit 8b6c60bb178e3bc22c8c917f650153a960ea9ae6.
---
index.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/index.js b/index.js
index bc3db73a..478d2f86 100644
--- a/index.js
+++ b/index.js
@@ -93,7 +93,6 @@ function createMainWindow() {
contextIsolation: false,
preload: path.join(__dirname, "preload.js"),
nodeIntegrationInSubFrames: true,
- nodeIntegration: true,
nativeWindowOpen: true, // window.open return Window object(like in regular browsers), not BrowserWindowProxy
enableRemoteModule: true,
affinity: "main-window", // main window, and addition windows should work in one process
From 8291cdfc12d37b4902cc1bd2b32af975ba6d49f3 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 02:37:19 +0300
Subject: [PATCH 12/52] disable dev tools on electron-prompt
---
index.js | 4 +++-
menu.js | 6 ++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/index.js b/index.js
index 478d2f86..baa8c49c 100644
--- a/index.js
+++ b/index.js
@@ -37,7 +37,9 @@ if (config.get("options.proxy")) {
}
// Adds debug features like hotkeys for triggering dev tools and reload
-require("electron-debug")();
+require("electron-debug")({
+ showDevTools: false //disable dev tools on electron-prompt
+});
// Prevent window being garbage collected
let mainWindow;
diff --git a/menu.js b/menu.js
index b51fb516..9deef729 100644
--- a/menu.js
+++ b/menu.js
@@ -148,7 +148,7 @@ const mainMenuTemplate = (win) => [
type: "checkbox",
checked: !!config.get("options.proxy"),
click: (item) => {
- setProxy(item, win);
+ setProxy(item);
}
},
{
@@ -310,7 +310,7 @@ module.exports.setApplicationMenu = (win) => {
};
const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
-function setProxy(item, win) {
+function setProxy(item) {
prompt({
title: 'Set Proxy',
label: 'Enter Proxy Adress:',
@@ -325,8 +325,6 @@ function setProxy(item, win) {
.then((input) => {
if(input !== null) {
config.set("options.proxy", input);
- if(input === "")
- item.checked = false;
item.checked = (input === "") ? false : true;
} else { //user pressed cancel
item.checked = !item.checked; //reset checkbox
From 421fe6793022386ef21707e78f56739f5689ecf1 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 02:46:12 +0300
Subject: [PATCH 13/52] ignore proxy if equal to example
---
menu.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/menu.js b/menu.js
index 9deef729..9dd0b8e2 100644
--- a/menu.js
+++ b/menu.js
@@ -310,11 +310,12 @@ module.exports.setApplicationMenu = (win) => {
};
const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
+const example = `Example: "socks5://127.0.0.1:9999"`;
function setProxy(item) {
prompt({
title: 'Set Proxy',
- label: 'Enter Proxy Adress:',
- value: config.get("options.proxy") || `Example - "socks5://127.0.0.1:9999"`,
+ label: 'Enter Proxy Adress (or leave empty to disable)',
+ value: config.get("options.proxy") || example,
inputAttrs: {
type: 'text'
},
@@ -323,7 +324,7 @@ function setProxy(item) {
icon: iconPath
})
.then((input) => {
- if(input !== null) {
+ if(input !== null && input !== example) {
config.set("options.proxy", input);
item.checked = (input === "") ? false : true;
} else { //user pressed cancel
From d12d16348aff03d6659a0211976d597c50396331 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 15:06:14 +0300
Subject: [PATCH 14/52] custom dark skin for prompt
---
darkPrompt.css | 37 +++++++++++++++++++++++++++++++++++++
menu.js | 5 +++--
2 files changed, 40 insertions(+), 2 deletions(-)
create mode 100644 darkPrompt.css
diff --git a/darkPrompt.css b/darkPrompt.css
new file mode 100644
index 00000000..100a6ed5
--- /dev/null
+++ b/darkPrompt.css
@@ -0,0 +1,37 @@
+body {
+ background-color: rgba(0, 0, 0, 0.3);
+ background-image: linear-gradient(315deg, #200000 0%, #13253a 74%);
+ overflow: hidden;
+ color:whitesmoke;
+}
+#container {
+ background: rgba( 0, 0, 0, 0.7 );
+ box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 );
+ backdrop-filter: blur( 10.0px );
+ -webkit-backdrop-filter: blur( 10.0px );
+ border-radius: 10px;
+ border: 1px solid rgba(80, 0, 0, 0.4);
+
+ overflow: hidden;
+}
+
+#data {
+ background: unset;
+ color: whitesmoke;
+ border: 1px solid rgb(54, 54, 54);
+}
+
+#data:focus {
+ outline: unset;
+ border: 1px solid rgb(85, 85, 85);
+}
+
+ #ok:focus, #cancel:focus {
+ outline: rgba(30, 0, 0, 0.3) solid 1px;
+ border: 1px solid rgba(60, 0, 0, 0.4);
+}
+
+#ok, #cancel {
+ background-color: rgb(0, 0, 0);
+ color: whitesmoke;
+}
\ No newline at end of file
diff --git a/menu.js b/menu.js
index 9dd0b8e2..bbe7204f 100644
--- a/menu.js
+++ b/menu.js
@@ -314,14 +314,15 @@ const example = `Example: "socks5://127.0.0.1:9999"`;
function setProxy(item) {
prompt({
title: 'Set Proxy',
- label: 'Enter Proxy Adress (or leave empty to disable)',
+ label: 'Enter Proxy Address (leave empty to disable)',
value: config.get("options.proxy") || example,
inputAttrs: {
type: 'text'
},
type: 'input',
alwaysOnTop: true,
- icon: iconPath
+ icon: iconPath,
+ customStylesheet: path.join(__dirname, "darkPrompt.css"),
})
.then((input) => {
if(input !== null && input !== example) {
From 7c8e946871fba05e5cbedcf9fa5e9b7a33117ccf Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 19:58:25 +0300
Subject: [PATCH 15/52] implement custom prompt
---
menu.js | 18 ++-
package.json | 2 +-
prompt/customTitlebar.js | 12 ++
darkPrompt.css => prompt/darkPrompt.css | 11 +-
prompt/index.js | 127 ++++++++++++++++++
prompt/page/prompt.css | 72 ++++++++++
prompt/page/prompt.html | 18 +++
prompt/page/prompt.js | 170 ++++++++++++++++++++++++
yarn.lock | 7 -
9 files changed, 424 insertions(+), 13 deletions(-)
create mode 100644 prompt/customTitlebar.js
rename darkPrompt.css => prompt/darkPrompt.css (88%)
create mode 100644 prompt/index.js
create mode 100644 prompt/page/prompt.css
create mode 100644 prompt/page/prompt.html
create mode 100644 prompt/page/prompt.js
diff --git a/menu.js b/menu.js
index bbe7204f..0312778f 100644
--- a/menu.js
+++ b/menu.js
@@ -6,7 +6,7 @@ const is = require("electron-is");
const { getAllPlugins } = require("./plugins/utils");
const config = require("./config");
-const prompt = require('electron-prompt');
+const prompt = require('./prompt');
const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
label: label || plugin,
@@ -312,7 +312,7 @@ module.exports.setApplicationMenu = (win) => {
const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
const example = `Example: "socks5://127.0.0.1:9999"`;
function setProxy(item) {
- prompt({
+ let options = {
title: 'Set Proxy',
label: 'Enter Proxy Address (leave empty to disable)',
value: config.get("options.proxy") || example,
@@ -322,8 +322,18 @@ function setProxy(item) {
type: 'input',
alwaysOnTop: true,
icon: iconPath,
- customStylesheet: path.join(__dirname, "darkPrompt.css"),
- })
+ customStylesheet: path.join(__dirname, "prompt","darkPrompt.css"),
+ };
+ if (config.plugins.isEnabled("in-app-menu")) {
+ Object.assign(options, {
+ frame: false,
+ customScript: path.join(__dirname, "prompt","customTitlebar.js"),
+ enableRemoteModule: true,
+ height: 200,
+ width: 450,
+ })
+ }
+ prompt(options)
.then((input) => {
if(input !== null && input !== example) {
config.set("options.proxy", input);
diff --git a/package.json b/package.json
index 736374c5..36591897 100644
--- a/package.json
+++ b/package.json
@@ -70,11 +70,11 @@
"browser-id3-writer": "^4.4.0",
"custom-electron-titlebar": "^3.2.6",
"discord-rpc": "^3.2.0",
+ "doc-ready": "^1.0.4",
"downloads-folder": "^3.0.1",
"electron-debug": "^3.2.0",
"electron-is": "^3.0.0",
"electron-localshortcut": "^3.2.1",
- "electron-prompt": "^1.6.2",
"electron-store": "^7.0.2",
"electron-unhandled": "^3.0.2",
"electron-updater": "^4.3.6",
diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js
new file mode 100644
index 00000000..203828d4
--- /dev/null
+++ b/prompt/customTitlebar.js
@@ -0,0 +1,12 @@
+const customTitlebar = require("custom-electron-titlebar");
+
+module.exports = () => {
+ const bar = new customTitlebar.Titlebar({
+ backgroundColor: customTitlebar.Color.fromHex("#050505"),
+ });
+ try {
+ bar.updateMenu(null);
+ } catch (e) {
+ //will always throw type error - null isn't menu, but it works
+ }
+}
\ No newline at end of file
diff --git a/darkPrompt.css b/prompt/darkPrompt.css
similarity index 88%
rename from darkPrompt.css
rename to prompt/darkPrompt.css
index 100a6ed5..3bdc5647 100644
--- a/darkPrompt.css
+++ b/prompt/darkPrompt.css
@@ -4,6 +4,16 @@ body {
overflow: hidden;
color:whitesmoke;
}
+
+::-webkit-scrollbar {
+ width: 0 !important;
+ display: none;
+}
+
+#label {
+ text-align: center;
+}
+
#container {
background: rgba( 0, 0, 0, 0.7 );
box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 );
@@ -11,7 +21,6 @@ body {
-webkit-backdrop-filter: blur( 10.0px );
border-radius: 10px;
border: 1px solid rgba(80, 0, 0, 0.4);
-
overflow: hidden;
}
diff --git a/prompt/index.js b/prompt/index.js
new file mode 100644
index 00000000..d6664305
--- /dev/null
+++ b/prompt/index.js
@@ -0,0 +1,127 @@
+const electron = require('electron');
+
+const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;
+const ipcMain = electron.ipcMain || electron.remote.ipcMain;
+const url = require('url');
+const path = require('path');
+
+const DEFAULT_WIDTH = 370;
+const DEFAULT_HEIGHT = 160;
+
+function electronPrompt(options, parentWindow) {
+ return new Promise((resolve, reject) => {
+ const id = `${Date.now()}-${Math.random()}`;
+
+ const options_ = Object.assign(
+ {
+ width: DEFAULT_WIDTH,
+ height: DEFAULT_HEIGHT,
+ minWidth: DEFAULT_WIDTH,
+ minHeight: DEFAULT_HEIGHT,
+ resizable: false,
+ title: 'Prompt',
+ label: 'Please input a value:',
+ buttonLabels: null,
+ alwaysOnTop: false,
+ value: null,
+ type: 'input',
+ selectOptions: null,
+ icon: null,
+ useHtmlLabel: false,
+ customStylesheet: null,
+ menuBarVisible: false,
+ skipTaskbar: true,
+ frame: true,
+ customScript: null,
+ enableRemoteModule: false
+ },
+ options || {}
+ );
+
+ if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) {
+ reject(new Error('"selectOptions" must be an object'));
+ return;
+ }
+
+ let promptWindow = new BrowserWindow({
+ frame: options_.frame,
+ width: options_.width,
+ height: options_.height,
+ minWidth: options_.minWidth,
+ minHeight: options_.minHeight,
+ resizable: options_.resizable,
+ minimizable: false,
+ fullscreenable: false,
+ maximizable: false,
+ parent: parentWindow,
+ skipTaskbar: options_.skipTaskbar,
+ alwaysOnTop: options_.alwaysOnTop,
+ useContentSize: options_.resizable,
+ modal: Boolean(parentWindow),
+ title: options_.title,
+ icon: options_.icon || undefined,
+ webPreferences: {
+ nodeIntegration: true,
+ contextIsolation: false,
+ enableRemoteModule: options_.enableRemoteModule
+ }
+ });
+
+ promptWindow.setMenu(null);
+ promptWindow.setMenuBarVisibility(options_.menuBarVisible);
+
+ const getOptionsListener = event => {
+ event.returnValue = JSON.stringify(options_);
+ };
+
+ const cleanup = () => {
+ ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener);
+ ipcMain.removeListener('prompt-post-data:' + id, postDataListener);
+ ipcMain.removeListener('prompt-error:' + id, errorListener);
+
+ if (promptWindow) {
+ promptWindow.close();
+ promptWindow = null;
+ }
+ };
+
+ const postDataListener = (event, value) => {
+ resolve(value);
+ event.returnValue = null;
+ cleanup();
+ };
+
+ const unresponsiveListener = () => {
+ reject(new Error('Window was unresponsive'));
+ cleanup();
+ };
+
+ const errorListener = (event, message) => {
+ reject(new Error(message));
+ event.returnValue = null;
+ cleanup();
+ };
+
+ ipcMain.on('prompt-get-options:' + id, getOptionsListener);
+ ipcMain.on('prompt-post-data:' + id, postDataListener);
+ ipcMain.on('prompt-error:' + id, errorListener);
+ promptWindow.on('unresponsive', unresponsiveListener);
+
+ promptWindow.on('closed', () => {
+ promptWindow = null;
+ cleanup();
+ resolve(null);
+ });
+
+ const promptUrl = url.format({
+ protocol: 'file',
+ slashes: true,
+ pathname: path.join(__dirname, 'page', 'prompt.html'),
+ hash: id
+ });
+
+ promptWindow.loadURL(promptUrl);
+ });
+}
+
+module.exports = electronPrompt;
diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css
new file mode 100644
index 00000000..b9d37777
--- /dev/null
+++ b/prompt/page/prompt.css
@@ -0,0 +1,72 @@
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
+ line-height: 1.5em;
+ color: #333;
+ background-color: #fff;
+}
+
+#container {
+ align-items: center;
+ justify-content: center;
+ display: flex;
+ height: 100%;
+ overflow: auto;
+}
+
+#form {
+ width: 100%;
+ padding-top: .5em;
+}
+
+#label {
+ max-width: 100%;
+ max-height: 100%;
+ margin-bottom: .8em;
+ padding: 0 .5em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+#data {
+ border-radius: 2px;
+ background: #fff;
+ width: 90%;
+ padding: .4em .5em;
+ border: 1px solid black;
+ min-height: 2em;
+ margin: 0 0 1.2em;
+}
+
+select#data {
+ height: 2em;
+}
+
+#data-container {
+ text-align: center;
+}
+
+#buttons {
+ text-align: right;
+ padding: 0 .5em 0 0;
+}
+
+#buttons > button,
+#buttons > input[type=submit] {
+ border-radius: 2px;
+ border: 0;
+ margin: 0 0 0 .5em;
+ font-size: .8em;
+ line-height: 1em;
+ padding: .6em 1em
+}
+
+#ok {
+ background-color: #3879D9;
+ color: white;
+}
+
+#cancel {
+ background-color: #DDD;
+ color: black;
+}
diff --git a/prompt/page/prompt.html b/prompt/page/prompt.html
new file mode 100644
index 00000000..cdbfa544
--- /dev/null
+++ b/prompt/page/prompt.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
diff --git a/prompt/page/prompt.js b/prompt/page/prompt.js
new file mode 100644
index 00000000..754d0e74
--- /dev/null
+++ b/prompt/page/prompt.js
@@ -0,0 +1,170 @@
+const fs = require('fs');
+const {ipcRenderer} = require('electron');
+const docReady = require('doc-ready');
+
+let promptId = null;
+let promptOptions = null;
+
+function promptError(error) {
+ if (error instanceof Error) {
+ error = error.message;
+ }
+
+ ipcRenderer.sendSync('prompt-error:' + promptId, error);
+}
+
+function promptCancel() {
+ ipcRenderer.sendSync('prompt-post-data:' + promptId, null);
+}
+
+function promptSubmit() {
+ const dataElement = document.querySelector('#data');
+ let data = null;
+
+ if (promptOptions.type === 'input') {
+ data = dataElement.value;
+ } else if (promptOptions.type === 'select') {
+ if (promptOptions.selectMultiple) {
+ data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value'));
+ } else {
+ data = dataElement.value;
+ }
+ }
+
+ ipcRenderer.sendSync('prompt-post-data:' + promptId, data);
+}
+
+function promptCreateInput() {
+ const dataElement = document.createElement('input');
+ dataElement.setAttribute('type', 'text');
+
+ if (promptOptions.value) {
+ dataElement.value = promptOptions.value;
+ } else {
+ dataElement.value = '';
+ }
+
+ if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') {
+ for (const k in promptOptions.inputAttrs) {
+ if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
+ continue;
+ }
+
+ dataElement.setAttribute(k, promptOptions.inputAttrs[k]);
+ }
+ }
+
+ dataElement.addEventListener('keyup', event => {
+ if (event.key === 'Escape') {
+ promptCancel();
+ }
+ });
+
+ dataElement.addEventListener('keypress', event => {
+ if (event.key === 'Enter') {
+ event.preventDefault();
+ document.querySelector('#ok').click();
+ }
+ });
+
+ return dataElement;
+}
+
+function promptCreateSelect() {
+ const dataElement = document.createElement('select');
+ let optionElement;
+
+ for (const k in promptOptions.selectOptions) {
+ if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) {
+ continue;
+ }
+
+ optionElement = document.createElement('option');
+ optionElement.setAttribute('value', k);
+ optionElement.textContent = promptOptions.selectOptions[k];
+ if (k === promptOptions.value) {
+ optionElement.setAttribute('selected', 'selected');
+ }
+
+ dataElement.append(optionElement);
+ }
+
+ return dataElement;
+}
+
+function promptRegister() {
+ promptId = document.location.hash.replace('#', '');
+
+ try {
+ promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId));
+ } catch (error) {
+ return promptError(error);
+ }
+
+ if (promptOptions.useHtmlLabel) {
+ document.querySelector('#label').innerHTML = promptOptions.label;
+ } else {
+ document.querySelector('#label').textContent = promptOptions.label;
+ }
+
+ if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
+ document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok;
+ }
+
+ if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
+ document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel;
+ }
+
+ if (promptOptions.customStylesheet) {
+ try {
+ const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
+ if (customStyleContent) {
+ const customStyle = document.createElement('style');
+ customStyle.setAttribute('rel', 'stylesheet');
+ customStyle.append(document.createTextNode(customStyleContent));
+ document.head.append(customStyle);
+ }
+ } catch (error) {
+ return promptError(error);
+ }
+ }
+
+ document.querySelector('#form').addEventListener('submit', promptSubmit);
+ document.querySelector('#cancel').addEventListener('click', promptCancel);
+
+ const dataContainerElement = document.querySelector('#data-container');
+
+ let dataElement;
+ if (promptOptions.type === 'input') {
+ dataElement = promptCreateInput();
+ } else if (promptOptions.type === 'select') {
+ dataElement = promptCreateSelect();
+ } else {
+ return promptError(`Unhandled input type '${promptOptions.type}'`);
+ }
+
+ dataContainerElement.append(dataElement);
+ dataElement.setAttribute('id', 'data');
+
+ dataElement.focus();
+ if (promptOptions.type === 'input') {
+ dataElement.select();
+ }
+
+ if (promptOptions.customScript) {
+ try {
+ const customScript = require(promptOptions.customScript);
+ customScript();
+ } catch (error) {
+ return promptError(error);
+ }
+ }
+}
+
+window.addEventListener('error', error => {
+ if (promptId) {
+ promptError('An error has occured on the prompt window: \n' + error);
+ }
+});
+
+docReady(promptRegister);
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index b029d432..f9909214 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3093,13 +3093,6 @@ electron-localshortcut@^3.1.0, electron-localshortcut@^3.2.1:
keyboardevent-from-electron-accelerator "^2.0.0"
keyboardevents-areequal "^0.2.1"
-electron-prompt@^1.6.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/electron-prompt/-/electron-prompt-1.6.2.tgz#e26bd3d359120bd45ce2f9625bdc380deb7ee269"
- integrity sha512-gC9ZpMopIgz1kW92J7UfsXarkLdPH2zhr77bnJFlDSduYjRlr9nEPm4ux1vyzJsO72AdOyvuPPIQB0j+gWsncQ==
- dependencies:
- doc-ready "^1.0.4"
-
electron-publish@22.9.1:
version "22.9.1"
resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.9.1.tgz#7cc76ac4cc53efd29ee31c1e5facb9724329068e"
From 73b0ddc2cecb08509a17bef4d222e8f5b183599e Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 21:25:41 +0300
Subject: [PATCH 16/52] css tweaks
---
prompt/customTitlebar.js | 7 +++++++
prompt/darkPrompt.css | 17 +++++++++--------
prompt/page/prompt.css | 8 +++++++-
3 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js
index 203828d4..5dc942cf 100644
--- a/prompt/customTitlebar.js
+++ b/prompt/customTitlebar.js
@@ -3,10 +3,17 @@ const customTitlebar = require("custom-electron-titlebar");
module.exports = () => {
const bar = new customTitlebar.Titlebar({
backgroundColor: customTitlebar.Color.fromHex("#050505"),
+ minimizable: false,
+ maximizable: false,
+ unfocusEffect: true,
});
try {
bar.updateMenu(null);
} catch (e) {
//will always throw type error - null isn't menu, but it works
}
+ let container = document.querySelector('#container');
+ container.style.width = '100%';
+ container.style.position = 'fixed';
+ container.style.border = 'unset';
}
\ No newline at end of file
diff --git a/prompt/darkPrompt.css b/prompt/darkPrompt.css
index 3bdc5647..311c42b5 100644
--- a/prompt/darkPrompt.css
+++ b/prompt/darkPrompt.css
@@ -1,15 +1,10 @@
+
body {
background-color: rgba(0, 0, 0, 0.3);
background-image: linear-gradient(315deg, #200000 0%, #13253a 74%);
- overflow: hidden;
color:whitesmoke;
}
-::-webkit-scrollbar {
- width: 0 !important;
- display: none;
-}
-
#label {
text-align: center;
}
@@ -30,14 +25,20 @@ body {
border: 1px solid rgb(54, 54, 54);
}
+#data:hover {
+ border: 1px solid rgb(85, 85, 85);
+}
+
#data:focus {
outline: unset;
border: 1px solid rgb(85, 85, 85);
}
- #ok:focus, #cancel:focus {
- outline: rgba(30, 0, 0, 0.3) solid 1px;
+ #ok:hover, #cancel:hover {
+ outline: rgba(60, 0, 0, 0.4) solid 2px;
+ /*
border: 1px solid rgba(60, 0, 0, 0.4);
+ */
}
#ok, #cancel {
diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css
index b9d37777..b18d1fc0 100644
--- a/prompt/page/prompt.css
+++ b/prompt/page/prompt.css
@@ -3,6 +3,12 @@ body {
line-height: 1.5em;
color: #333;
background-color: #fff;
+ overflow-y: hidden;
+}
+
+::-webkit-scrollbar {
+ width: 0 !important;
+ display: none;
}
#container {
@@ -10,7 +16,7 @@ body {
justify-content: center;
display: flex;
height: 100%;
- overflow: auto;
+ overflow-y: hidden;
}
#form {
From 10e29090d8318555d6ca7860d2ce00d9fcc3ce9e Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 4 Apr 2021 21:52:16 +0300
Subject: [PATCH 17/52] stylecheck
---
menu.js | 41 ++++++++-----------
prompt/customTitlebar.js | 4 +-
prompt/darkPrompt.css | 52 ++++++++++++------------
prompt/page/prompt.css | 88 ++++++++++++++++++++--------------------
4 files changed, 90 insertions(+), 95 deletions(-)
diff --git a/menu.js b/menu.js
index 0312778f..18764681 100644
--- a/menu.js
+++ b/menu.js
@@ -148,7 +148,7 @@ const mainMenuTemplate = (win) => [
type: "checkbox",
checked: !!config.get("options.proxy"),
click: (item) => {
- setProxy(item);
+ setProxy(item, win);
}
},
{
@@ -311,36 +311,31 @@ module.exports.setApplicationMenu = (win) => {
const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
const example = `Example: "socks5://127.0.0.1:9999"`;
-function setProxy(item) {
+function setProxy(item, win) {
let options = {
title: 'Set Proxy',
- label: 'Enter Proxy Address (leave empty to disable)',
+ label: 'Enter Proxy Address: (leave empty to disable)',
value: config.get("options.proxy") || example,
inputAttrs: {
type: 'text'
},
type: 'input',
- alwaysOnTop: true,
icon: iconPath,
- customStylesheet: path.join(__dirname, "prompt","darkPrompt.css"),
+ customStylesheet: path.join(__dirname, "prompt", "darkPrompt.css"),
+ frame: false,
+ customScript: path.join(__dirname, "prompt", "customTitlebar.js"),
+ enableRemoteModule: true,
+ height: 200,
+ width: 450,
};
- if (config.plugins.isEnabled("in-app-menu")) {
- Object.assign(options, {
- frame: false,
- customScript: path.join(__dirname, "prompt","customTitlebar.js"),
- enableRemoteModule: true,
- height: 200,
- width: 450,
+ prompt(options, win)
+ .then((input) => {
+ if (input !== null && input !== example) {
+ config.set("options.proxy", input);
+ item.checked = (input === "") ? false : true;
+ } else { //user pressed cancel
+ item.checked = !item.checked; //reset checkbox
+ }
})
- }
- prompt(options)
- .then((input) => {
- if(input !== null && input !== example) {
- config.set("options.proxy", input);
- item.checked = (input === "") ? false : true;
- } else { //user pressed cancel
- item.checked = !item.checked; //reset checkbox
- }
- })
- .catch(console.error);
+ .catch(console.error);
}
\ No newline at end of file
diff --git a/prompt/customTitlebar.js b/prompt/customTitlebar.js
index 5dc942cf..116aa56c 100644
--- a/prompt/customTitlebar.js
+++ b/prompt/customTitlebar.js
@@ -2,11 +2,11 @@ const customTitlebar = require("custom-electron-titlebar");
module.exports = () => {
const bar = new customTitlebar.Titlebar({
- backgroundColor: customTitlebar.Color.fromHex("#050505"),
+ backgroundColor: customTitlebar.Color.fromHex("#050505"),
minimizable: false,
maximizable: false,
unfocusEffect: true,
- });
+ });
try {
bar.updateMenu(null);
} catch (e) {
diff --git a/prompt/darkPrompt.css b/prompt/darkPrompt.css
index 311c42b5..8b343a25 100644
--- a/prompt/darkPrompt.css
+++ b/prompt/darkPrompt.css
@@ -1,47 +1,45 @@
-
body {
- background-color: rgba(0, 0, 0, 0.3);
- background-image: linear-gradient(315deg, #200000 0%, #13253a 74%);
- color:whitesmoke;
+ background-color: rgba(0, 0, 0, 0.3);
+ background-image: linear-gradient(315deg, #200000 0%, #13253a 74%);
+ color: whitesmoke;
}
#label {
- text-align: center;
+ text-align: center;
}
#container {
- background: rgba( 0, 0, 0, 0.7 );
- box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 );
- backdrop-filter: blur( 10.0px );
- -webkit-backdrop-filter: blur( 10.0px );
- border-radius: 10px;
- border: 1px solid rgba(80, 0, 0, 0.4);
- overflow: hidden;
+ background: rgba(0, 0, 0, 0.7);
+ box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
+ backdrop-filter: blur(10px);
+ -webkit-backdrop-filter: blur(10px);
+ border-radius: 10px;
+ border: 1px solid rgba(80, 0, 0, 0.4);
+ overflow: hidden;
}
#data {
- background: unset;
- color: whitesmoke;
- border: 1px solid rgb(54, 54, 54);
+ background: unset;
+ color: whitesmoke;
+ border: 1px solid rgb(54, 54, 54);
}
#data:hover {
- border: 1px solid rgb(85, 85, 85);
+ border: 1px solid rgb(85, 85, 85);
}
#data:focus {
- outline: unset;
- border: 1px solid rgb(85, 85, 85);
+ outline: unset;
+ border: 1px solid rgb(85, 85, 85);
}
- #ok:hover, #cancel:hover {
- outline: rgba(60, 0, 0, 0.4) solid 2px;
- /*
- border: 1px solid rgba(60, 0, 0, 0.4);
- */
+#ok:hover,
+#cancel:hover {
+ outline: rgba(60, 0, 0, 0.4) solid 2px;
}
-#ok, #cancel {
- background-color: rgb(0, 0, 0);
- color: whitesmoke;
-}
\ No newline at end of file
+#ok,
+#cancel {
+ background-color: rgb(0, 0, 0);
+ color: whitesmoke;
+}
diff --git a/prompt/page/prompt.css b/prompt/page/prompt.css
index b18d1fc0..c3530e57 100644
--- a/prompt/page/prompt.css
+++ b/prompt/page/prompt.css
@@ -1,78 +1,80 @@
body {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
- line-height: 1.5em;
- color: #333;
- background-color: #fff;
- overflow-y: hidden;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial,
+ sans-serif;
+ line-height: 1.5em;
+ color: #333;
+ background-color: #fff;
+ overflow-y: hidden;
}
::-webkit-scrollbar {
- width: 0 !important;
- display: none;
+ width: 0 !important;
+ display: none;
}
#container {
- align-items: center;
- justify-content: center;
- display: flex;
- height: 100%;
- overflow-y: hidden;
+ align-items: center;
+ justify-content: center;
+ display: flex;
+ height: 100%;
+ overflow-y: hidden;
}
#form {
- width: 100%;
- padding-top: .5em;
+ width: 100%;
+ padding-top: 0.5em;
}
#label {
- max-width: 100%;
- max-height: 100%;
- margin-bottom: .8em;
- padding: 0 .5em;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
+ max-width: 100%;
+ max-height: 100%;
+ margin-bottom: 0.8em;
+ padding: 0 0.5em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
#data {
- border-radius: 2px;
- background: #fff;
- width: 90%;
- padding: .4em .5em;
- border: 1px solid black;
- min-height: 2em;
- margin: 0 0 1.2em;
+ border-radius: 2px;
+ background: #fff;
+ width: 90%;
+ padding: 0.4em 0.5em;
+ border: 1px solid black;
+ min-height: 2em;
+ margin: 0 0 1.2em;
}
select#data {
- height: 2em;
+ height: 2em;
}
#data-container {
- text-align: center;
+ text-align: center;
}
#buttons {
- text-align: right;
- padding: 0 .5em 0 0;
+ text-align: right;
+ padding: 0 0.5em 0 0;
}
#buttons > button,
-#buttons > input[type=submit] {
- border-radius: 2px;
- border: 0;
- margin: 0 0 0 .5em;
- font-size: .8em;
- line-height: 1em;
- padding: .6em 1em
+#buttons > input[type="submit"] {
+ border-radius: 2px;
+ border: 0;
+ margin: 0 0 0 0.5em;
+ font-size: 0.8em;
+ line-height: 1em;
+ padding: 0.6em 1em;
}
#ok {
- background-color: #3879D9;
- color: white;
+ background-color: #3879d9;
+ color: white;
}
#cancel {
- background-color: #DDD;
- color: black;
+ background-color: #ddd;
+ color: black;
}
From 28d366ab19cdf85fdad4537db9762e40c86d4da6 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 03:04:06 +0300
Subject: [PATCH 18/52] add back-to-front logger
This somehow fix "did-fail-load" being called on song start, with in-app-plugin-activated
---
index.js | 23 +++++++++++++++++++++--
preload.js | 4 ++++
providers/logger.js | 14 ++++++++++++++
3 files changed, 39 insertions(+), 2 deletions(-)
create mode 100644 providers/logger.js
diff --git a/index.js b/index.js
index baa8c49c..97f4dcb5 100644
--- a/index.js
+++ b/index.js
@@ -163,10 +163,29 @@ app.on("browser-window-created", (event, win) => {
createdWindow = true;
loadPlugins(win);
- win.webContents.on("did-fail-load", () => {
+ win.webContents.on("did-fail-load", (
+ event,
+ errorCode,
+ errorDescription,
+ validatedURL,
+ isMainFrame,
+ frameProcessId,
+ frameRoutingId,
+ ) => {
+ let log = {
+ error: "did-fail-load",
+ event,
+ errorCode,
+ errorDescription,
+ validatedURL,
+ isMainFrame,
+ frameProcessId,
+ frameRoutingId,
+ };
if (is.dev()) {
- console.log("did fail load");
+ console.log(log);
}
+ win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
});
diff --git a/preload.js b/preload.js
index 94f2a72a..33e67306 100644
--- a/preload.js
+++ b/preload.js
@@ -32,6 +32,10 @@ document.addEventListener("DOMContentLoaded", () => {
// inject song-info provider
const songInfoProviderPath = path.join(__dirname, "providers", "song-info-front.js")
fileExists(songInfoProviderPath, require(songInfoProviderPath));
+
+ // inject front logger
+ const loggerPath = path.join(__dirname, "providers", "logger.js")
+ fileExists(loggerPath, require(loggerPath));
// Add action for reloading
global.reload = () =>
diff --git a/providers/logger.js b/providers/logger.js
new file mode 100644
index 00000000..84163c52
--- /dev/null
+++ b/providers/logger.js
@@ -0,0 +1,14 @@
+const { ipcRenderer } = require("electron");
+
+module.exports = () => {
+ ipcRenderer.on("log", (event, log) => {
+ let string = log.toString() || log;
+ if (string) {
+ console.log(string);
+ } else {
+ for (let propery of log) {
+ console.log(propery.toString() || propery);
+ }
+ }
+ })
+}
\ No newline at end of file
From 11bd1adbd406160b9ee4215fa0b329b5ecd4391d Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 03:25:45 +0300
Subject: [PATCH 19/52] stylecheck
---
index.js | 32 ++++++++++++++++----------------
preload.js | 2 +-
providers/logger.js | 18 +++++++++---------
3 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/index.js b/index.js
index 97f4dcb5..9e8b7233 100644
--- a/index.js
+++ b/index.js
@@ -37,8 +37,8 @@ if (config.get("options.proxy")) {
}
// Adds debug features like hotkeys for triggering dev tools and reload
-require("electron-debug")({
- showDevTools: false //disable dev tools on electron-prompt
+require("electron-debug")({
+ showDevTools: false //disable automatic devTools on new window
});
// Prevent window being garbage collected
@@ -100,18 +100,18 @@ 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,
titleBarStyle: useInlineMenu
? "hidden"
: is.macOS()
- ? "hiddenInset"
- : "default",
+ ? "hiddenInset"
+ : "default",
autoHideMenuBar: config.get("options.hideMenu"),
});
if (windowPosition) {
@@ -157,20 +157,20 @@ function createMainWindow() {
let createdWindow = false;
app.on("browser-window-created", (event, win) => {
//Ensure listeners aren't registered when creating input dialog
- if(createdWindow){
+ if (createdWindow) {
return;
}
createdWindow = true;
loadPlugins(win);
win.webContents.on("did-fail-load", (
- event,
- errorCode,
- errorDescription,
- validatedURL,
- isMainFrame,
- frameProcessId,
- frameRoutingId,
+ event,
+ errorCode,
+ errorDescription,
+ validatedURL,
+ isMainFrame,
+ frameProcessId,
+ frameRoutingId,
) => {
let log = {
error: "did-fail-load",
diff --git a/preload.js b/preload.js
index 33e67306..f25dd6b7 100644
--- a/preload.js
+++ b/preload.js
@@ -36,7 +36,7 @@ document.addEventListener("DOMContentLoaded", () => {
// inject front logger
const loggerPath = path.join(__dirname, "providers", "logger.js")
fileExists(loggerPath, require(loggerPath));
-
+
// Add action for reloading
global.reload = () =>
remote.getCurrentWindow().webContents.loadURL(config.get("url"));
diff --git a/providers/logger.js b/providers/logger.js
index 84163c52..560b696b 100644
--- a/providers/logger.js
+++ b/providers/logger.js
@@ -2,13 +2,13 @@ const { ipcRenderer } = require("electron");
module.exports = () => {
ipcRenderer.on("log", (event, log) => {
- let string = log.toString() || log;
- if (string) {
- console.log(string);
- } else {
- for (let propery of log) {
- console.log(propery.toString() || propery);
- }
- }
- })
+ let string = log.toString() || log;
+ if (string) {
+ console.log(string);
+ } else {
+ for (let propery of log) {
+ console.log(propery.toString() || propery);
+ }
+ }
+ })
}
\ No newline at end of file
From 6472002f8a441f21a746b72fc876433698b19190 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 04:04:29 +0300
Subject: [PATCH 20/52] fix hide-menu timing + minify log function
---
plugins/in-app-menu/back.js | 35 ++++++++++++++++++++++-------------
providers/logger.js | 13 +++++--------
2 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 53bb9f8d..5c17317a 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -8,7 +8,9 @@ const { setApplicationMenu } = require("../../menu");
const { injectCSS } = require("../utils");
//check that menu doesn't get created twice
-let done = false;
+let calledReadyToShow = false;
+//check menu state isn't changed twice
+let calledFinishedLoad = false
//tracks menu visibility
let visible = true;
// win hook for fixing menu
@@ -32,42 +34,49 @@ module.exports = (winImport) => {
win.on("ready-to-show", () => {
// (apparently ready-to-show is called twice)
- if (done) {
+ if (calledReadyToShow) {
return;
}
- done = true;
+ calledReadyToShow = true;
setApplicationMenu(win);
//register keyboard shortcut && hide menu if hideMenu is enabled
if (config.get("options.hideMenu")) {
- switchMenuVisibility();
electronLocalshortcut.register(win, "Esc", () => {
switchMenuVisibility();
});
- }
- // fix bug with menu not applying on start when no internet connection available
- setMenuVisibility(visible);
+ }
});
+
+ //set menu visibility on load
+ win.webContents.on("did-finish-load", () => {
+ if (calledFinishedLoad) {
+ return;
+ }
+ calledFinishedLoad = true;
+ // fix bug with menu not applying on start when no internet connection available
+ setMenuVisibility(!config.get("options.hideMenu"));
+ })
};
function switchMenuVisibility() {
setMenuVisibility(!visible);
}
-function setMenuVisibility(value){
+function setMenuVisibility(value) {
visible = value;
win.webContents.send("updateMenu", visible);
}
function updateCheckboxesAndRadioButtons(item, isRadio, hasSubmenu) {
if (!isRadio) {
- //fix checkbox
- item.checked = !item.checked;
- }
+ //fix checkbox
+ item.checked = !item.checked;
+ }
//update menu if radio / hasSubmenu
if (isRadio || hasSubmenu) {
- win.webContents.send("updateMenu", true);
+ win.webContents.send("updateMenu", true);
}
}
@@ -79,7 +88,7 @@ function updateTemplate(template) {
let originalOnclick = item.click;
item.click = (itemClicked) => {
originalOnclick(itemClicked);
- updateCheckboxesAndRadioButtons(itemClicked, item.type==='radio', item.hasSubmenu);
+ updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu);
};
item.fixed = true;
}
diff --git a/providers/logger.js b/providers/logger.js
index 560b696b..dc91f87b 100644
--- a/providers/logger.js
+++ b/providers/logger.js
@@ -3,12 +3,9 @@ const { ipcRenderer } = require("electron");
module.exports = () => {
ipcRenderer.on("log", (event, log) => {
let string = log.toString() || log;
- if (string) {
- console.log(string);
- } else {
- for (let propery of log) {
- console.log(propery.toString() || propery);
- }
- }
+ if (!string || string === "[object Object]") {
+ string = JSON.stringify(log);
+ }
+ console.log(string);
})
-}
\ No newline at end of file
+};
\ No newline at end of file
From 106e461beb5a7cc4a92f8970acd041cd1b09b8f9 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 04:08:55 +0300
Subject: [PATCH 21/52] fix typo
---
plugins/in-app-menu/back.js | 4 ----
providers/logger.js | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 5c17317a..b17ee032 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -51,10 +51,6 @@ module.exports = (winImport) => {
//set menu visibility on load
win.webContents.on("did-finish-load", () => {
- if (calledFinishedLoad) {
- return;
- }
- calledFinishedLoad = true;
// fix bug with menu not applying on start when no internet connection available
setMenuVisibility(!config.get("options.hideMenu"));
})
diff --git a/providers/logger.js b/providers/logger.js
index dc91f87b..08a940f3 100644
--- a/providers/logger.js
+++ b/providers/logger.js
@@ -2,7 +2,7 @@ const { ipcRenderer } = require("electron");
module.exports = () => {
ipcRenderer.on("log", (event, log) => {
- let string = log.toString() || log;
+ let string = log || log.toString();
if (!string || string === "[object Object]") {
string = JSON.stringify(log);
}
From 6d44a579a44f4420e6ab60e2c6655f7bcf2e429e Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 04:21:52 +0300
Subject: [PATCH 22/52] move prompt to provide
---
menu.js | 19 ++++++++++++-------
.../prompt}/customTitlebar.js | 0
{prompt => providers/prompt}/darkPrompt.css | 0
{prompt => providers/prompt}/index.js | 0
{prompt => providers/prompt}/page/prompt.css | 0
{prompt => providers/prompt}/page/prompt.html | 0
{prompt => providers/prompt}/page/prompt.js | 0
7 files changed, 12 insertions(+), 7 deletions(-)
rename {prompt => providers/prompt}/customTitlebar.js (100%)
rename {prompt => providers/prompt}/darkPrompt.css (100%)
rename {prompt => providers/prompt}/index.js (100%)
rename {prompt => providers/prompt}/page/prompt.css (100%)
rename {prompt => providers/prompt}/page/prompt.html (100%)
rename {prompt => providers/prompt}/page/prompt.js (100%)
diff --git a/menu.js b/menu.js
index 18764681..3754d14c 100644
--- a/menu.js
+++ b/menu.js
@@ -6,7 +6,7 @@ const is = require("electron-is");
const { getAllPlugins } = require("./plugins/utils");
const config = require("./config");
-const prompt = require('./prompt');
+const prompt = require('./providers/prompt');
const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
label: label || plugin,
@@ -321,13 +321,18 @@ function setProxy(item, win) {
},
type: 'input',
icon: iconPath,
- customStylesheet: path.join(__dirname, "prompt", "darkPrompt.css"),
- frame: false,
- customScript: path.join(__dirname, "prompt", "customTitlebar.js"),
- enableRemoteModule: true,
- height: 200,
- width: 450,
+ customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"),
};
+ //TODO: custom bar on prompt need testing on macOS
+ if(!is.macOS()) {
+ Object.assign(options, {
+ frame: false,
+ customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"),
+ enableRemoteModule: true,
+ height: 200,
+ width: 450,
+ });
+ }
prompt(options, win)
.then((input) => {
if (input !== null && input !== example) {
diff --git a/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js
similarity index 100%
rename from prompt/customTitlebar.js
rename to providers/prompt/customTitlebar.js
diff --git a/prompt/darkPrompt.css b/providers/prompt/darkPrompt.css
similarity index 100%
rename from prompt/darkPrompt.css
rename to providers/prompt/darkPrompt.css
diff --git a/prompt/index.js b/providers/prompt/index.js
similarity index 100%
rename from prompt/index.js
rename to providers/prompt/index.js
diff --git a/prompt/page/prompt.css b/providers/prompt/page/prompt.css
similarity index 100%
rename from prompt/page/prompt.css
rename to providers/prompt/page/prompt.css
diff --git a/prompt/page/prompt.html b/providers/prompt/page/prompt.html
similarity index 100%
rename from prompt/page/prompt.html
rename to providers/prompt/page/prompt.html
diff --git a/prompt/page/prompt.js b/providers/prompt/page/prompt.js
similarity index 100%
rename from prompt/page/prompt.js
rename to providers/prompt/page/prompt.js
From 25d0f50f3da69c2f59b27f5640d54315202e4c0b Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 04:52:22 +0300
Subject: [PATCH 23/52] Create readme.md
---
providers/prompt/readme.md | 76 ++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 providers/prompt/readme.md
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
new file mode 100644
index 00000000..2eb13b74
--- /dev/null
+++ b/providers/prompt/readme.md
@@ -0,0 +1,76 @@
+# Prompt Documentation
+
+
+
+## Usage
+
+```js
+prompt([options, parentBrowserWindow]).then(...).catch(...)
+```
+
+## Example
+
+```js
+const prompt = require('./providers/prompt');
+
+prompt({
+ title: 'Prompt example',
+ label: 'URL:',
+ value: 'http://example.org',
+ inputAttrs: {
+ type: 'url'
+ },
+ type: 'input'
+})
+.then((r) => {
+ if(r === null) {
+ console.log('user cancelled');
+ } else {
+ console.log('result', r);
+ }
+})
+.catch(console.error);
+```
+
+### Options object (optional)
+
+| Key | Explanation |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. |
+| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. |
+| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. |
+| value | (optional, string) The default value for the input field. Defaults to null. |
+| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. |
+| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input' |
+| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
+| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
+| width | (optional, integer) The width of the prompt window. Defaults to 370. |
+| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. |
+| height | (optional, integer) The height of the prompt window. Defaults to 130. |
+| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. |
+| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. |
+| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false |
+| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. |
+| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. |
+| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. |
+| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. |
+| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. |
+| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. |
+| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. |
+
+If not supplied, it uses the defaults listed in the table above.
+
+### parentBrowserWindow (optional)
+
+The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null.
+
+### customScript (optional)
+
+Create the script with the following template:
+
+```node
+module.exports = () => {
+ // This function will be called as a preload script
+ // So you can use front features like `document.querySelector`
+};
+```
From a215035d0792891845eeb625ba140fd3dadfb241 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 18:28:27 +0300
Subject: [PATCH 24/52] refactor and css fix
---
providers/prompt/customTitlebar.js | 15 +++++----------
providers/prompt/darkPrompt.css | 4 +++-
providers/prompt/index.js | 6 +++---
3 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js
index 116aa56c..6c508210 100644
--- a/providers/prompt/customTitlebar.js
+++ b/providers/prompt/customTitlebar.js
@@ -5,15 +5,10 @@ module.exports = () => {
backgroundColor: customTitlebar.Color.fromHex("#050505"),
minimizable: false,
maximizable: false,
- unfocusEffect: true,
+ menu: null
});
- try {
- bar.updateMenu(null);
- } catch (e) {
- //will always throw type error - null isn't menu, but it works
- }
- let container = document.querySelector('#container');
- container.style.width = '100%';
- container.style.position = 'fixed';
- container.style.border = 'unset';
+ let mainStyle = document.querySelector('#container').style;
+ mainStyle.width = '100%';
+ mainStyle.position = 'fixed';
+ mainStyle.border = 'unset';
}
\ No newline at end of file
diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/darkPrompt.css
index 8b343a25..49e0f88e 100644
--- a/providers/prompt/darkPrompt.css
+++ b/providers/prompt/darkPrompt.css
@@ -34,7 +34,9 @@ body {
}
#ok:hover,
-#cancel:hover {
+#ok:focus,
+#cancel:hover,
+#cancel:focus {
outline: rgba(60, 0, 0, 0.4) solid 2px;
}
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index d6664305..0d89ebe9 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -50,9 +50,9 @@ function electronPrompt(options, parentWindow) {
minWidth: options_.minWidth,
minHeight: options_.minHeight,
resizable: options_.resizable,
- minimizable: false,
- fullscreenable: false,
- maximizable: false,
+ minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop,
+ fullscreenable: options_.resizable,
+ maximizable: options_.resizable,
parent: parentWindow,
skipTaskbar: options_.skipTaskbar,
alwaysOnTop: options_.alwaysOnTop,
From 724c213af10c4ade43fb15b564fbb12123672ffb Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Mon, 5 Apr 2021 23:18:54 +0300
Subject: [PATCH 25/52] xo --fix
---
menu.js | 4 +-
package.json | 12 ++-
plugins/in-app-menu/back.js | 9 +-
providers/prompt/custom-titlebar.js | 14 +++
providers/prompt/customTitlebar.js | 14 ---
.../{darkPrompt.css => dark-prompt.css} | 0
providers/prompt/index.js | 30 +++----
providers/prompt/page/prompt.js | 88 +++++++++----------
8 files changed, 89 insertions(+), 82 deletions(-)
create mode 100644 providers/prompt/custom-titlebar.js
delete mode 100644 providers/prompt/customTitlebar.js
rename providers/prompt/{darkPrompt.css => dark-prompt.css} (100%)
diff --git a/menu.js b/menu.js
index 3754d14c..c0495d68 100644
--- a/menu.js
+++ b/menu.js
@@ -321,13 +321,13 @@ function setProxy(item, win) {
},
type: 'input',
icon: iconPath,
- customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"),
+ customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"),
};
//TODO: custom bar on prompt need testing on macOS
if(!is.macOS()) {
Object.assign(options, {
frame: false,
- customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"),
+ customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"),
enableRemoteModule: true,
height: 200,
width: 450,
diff --git a/package.json b/package.json
index 36591897..144ac53f 100644
--- a/package.json
+++ b/package.json
@@ -101,6 +101,16 @@
"envs": [
"node",
"browser"
- ]
+ ],
+ "rules": {
+ "quotes": [
+ "error",
+ "double",
+ {
+ "avoidEscape": true,
+ "allowTemplateLiterals": true
+ }
+ ]
+ }
}
}
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index b17ee032..938c5475 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -9,8 +9,6 @@ const { injectCSS } = require("../utils");
//check that menu doesn't get created twice
let calledReadyToShow = false;
-//check menu state isn't changed twice
-let calledFinishedLoad = false
//tracks menu visibility
let visible = true;
// win hook for fixing menu
@@ -37,6 +35,7 @@ module.exports = (winImport) => {
if (calledReadyToShow) {
return;
}
+
calledReadyToShow = true;
setApplicationMenu(win);
@@ -53,7 +52,7 @@ module.exports = (winImport) => {
win.webContents.on("did-finish-load", () => {
// fix bug with menu not applying on start when no internet connection available
setMenuVisibility(!config.get("options.hideMenu"));
- })
+ });
};
function switchMenuVisibility() {
@@ -81,10 +80,10 @@ 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);
- updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu);
+ updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu);
};
item.fixed = true;
}
diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js
new file mode 100644
index 00000000..c36ce5f5
--- /dev/null
+++ b/providers/prompt/custom-titlebar.js
@@ -0,0 +1,14 @@
+const customTitlebar = require("custom-electron-titlebar");
+
+module.exports = () => {
+ const bar = new customTitlebar.Titlebar({
+ backgroundColor: customTitlebar.Color.fromHex("#050505"),
+ minimizable: false,
+ maximizable: false,
+ menu: null
+ });
+ const mainStyle = document.querySelector("#container").style;
+ mainStyle.width = "100%";
+ mainStyle.position = "fixed";
+ mainStyle.border = "unset";
+};
diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js
deleted file mode 100644
index 6c508210..00000000
--- a/providers/prompt/customTitlebar.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const customTitlebar = require("custom-electron-titlebar");
-
-module.exports = () => {
- const bar = new customTitlebar.Titlebar({
- backgroundColor: customTitlebar.Color.fromHex("#050505"),
- minimizable: false,
- maximizable: false,
- menu: null
- });
- let mainStyle = document.querySelector('#container').style;
- mainStyle.width = '100%';
- mainStyle.position = 'fixed';
- mainStyle.border = 'unset';
-}
\ No newline at end of file
diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/dark-prompt.css
similarity index 100%
rename from providers/prompt/darkPrompt.css
rename to providers/prompt/dark-prompt.css
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 0d89ebe9..302eeea0 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -1,9 +1,9 @@
-const electron = require('electron');
+const electron = require("electron");
const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;
const ipcMain = electron.ipcMain || electron.remote.ipcMain;
-const url = require('url');
-const path = require('path');
+const url = require("url");
+const path = require("path");
const DEFAULT_WIDTH = 370;
const DEFAULT_HEIGHT = 160;
@@ -38,7 +38,7 @@ function electronPrompt(options, parentWindow) {
options || {}
);
- if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) {
+ if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
reject(new Error('"selectOptions" must be an object'));
return;
}
@@ -75,9 +75,9 @@ function electronPrompt(options, parentWindow) {
};
const cleanup = () => {
- ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener);
- ipcMain.removeListener('prompt-post-data:' + id, postDataListener);
- ipcMain.removeListener('prompt-error:' + id, errorListener);
+ ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener);
+ ipcMain.removeListener("prompt-post-data:" + id, postDataListener);
+ ipcMain.removeListener("prompt-error:" + id, errorListener);
if (promptWindow) {
promptWindow.close();
@@ -92,7 +92,7 @@ function electronPrompt(options, parentWindow) {
};
const unresponsiveListener = () => {
- reject(new Error('Window was unresponsive'));
+ reject(new Error("Window was unresponsive"));
cleanup();
};
@@ -102,21 +102,21 @@ function electronPrompt(options, parentWindow) {
cleanup();
};
- ipcMain.on('prompt-get-options:' + id, getOptionsListener);
- ipcMain.on('prompt-post-data:' + id, postDataListener);
- ipcMain.on('prompt-error:' + id, errorListener);
- promptWindow.on('unresponsive', unresponsiveListener);
+ ipcMain.on("prompt-get-options:" + id, getOptionsListener);
+ ipcMain.on("prompt-post-data:" + id, postDataListener);
+ ipcMain.on("prompt-error:" + id, errorListener);
+ promptWindow.on("unresponsive", unresponsiveListener);
- promptWindow.on('closed', () => {
+ promptWindow.on("closed", () => {
promptWindow = null;
cleanup();
resolve(null);
});
const promptUrl = url.format({
- protocol: 'file',
+ protocol: "file",
slashes: true,
- pathname: path.join(__dirname, 'page', 'prompt.html'),
+ pathname: path.join(__dirname, "page", "prompt.html"),
hash: id
});
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 754d0e74..67acd31d 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -1,6 +1,6 @@
-const fs = require('fs');
-const {ipcRenderer} = require('electron');
-const docReady = require('doc-ready');
+const fs = require("fs");
+const {ipcRenderer} = require("electron");
+const docReady = require("doc-ready");
let promptId = null;
let promptOptions = null;
@@ -10,41 +10,39 @@ function promptError(error) {
error = error.message;
}
- ipcRenderer.sendSync('prompt-error:' + promptId, error);
+ ipcRenderer.sendSync("prompt-error:" + promptId, error);
}
function promptCancel() {
- ipcRenderer.sendSync('prompt-post-data:' + promptId, null);
+ ipcRenderer.sendSync("prompt-post-data:" + promptId, null);
}
function promptSubmit() {
- const dataElement = document.querySelector('#data');
+ const dataElement = document.querySelector("#data");
let data = null;
- if (promptOptions.type === 'input') {
+ if (promptOptions.type === "input") {
data = dataElement.value;
- } else if (promptOptions.type === 'select') {
- if (promptOptions.selectMultiple) {
- data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value'));
- } else {
- data = dataElement.value;
- }
+ } else if (promptOptions.type === "select") {
+ data = promptOptions.selectMultiple ?
+ dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
+ dataElement.value;
}
- ipcRenderer.sendSync('prompt-post-data:' + promptId, data);
+ ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
}
function promptCreateInput() {
- const dataElement = document.createElement('input');
- dataElement.setAttribute('type', 'text');
+ const dataElement = document.createElement("input");
+ dataElement.setAttribute("type", "text");
if (promptOptions.value) {
dataElement.value = promptOptions.value;
} else {
- dataElement.value = '';
+ dataElement.value = "";
}
- if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') {
+ if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") {
for (const k in promptOptions.inputAttrs) {
if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
continue;
@@ -54,16 +52,16 @@ function promptCreateInput() {
}
}
- dataElement.addEventListener('keyup', event => {
- if (event.key === 'Escape') {
+ dataElement.addEventListener("keyup", event => {
+ if (event.key === "Escape") {
promptCancel();
}
});
- dataElement.addEventListener('keypress', event => {
- if (event.key === 'Enter') {
+ dataElement.addEventListener("keypress", event => {
+ if (event.key === "Enter") {
event.preventDefault();
- document.querySelector('#ok').click();
+ document.querySelector("#ok").click();
}
});
@@ -71,7 +69,7 @@ function promptCreateInput() {
}
function promptCreateSelect() {
- const dataElement = document.createElement('select');
+ const dataElement = document.createElement("select");
let optionElement;
for (const k in promptOptions.selectOptions) {
@@ -79,11 +77,11 @@ function promptCreateSelect() {
continue;
}
- optionElement = document.createElement('option');
- optionElement.setAttribute('value', k);
+ optionElement = document.createElement("option");
+ optionElement.setAttribute("value", k);
optionElement.textContent = promptOptions.selectOptions[k];
if (k === promptOptions.value) {
- optionElement.setAttribute('selected', 'selected');
+ optionElement.setAttribute("selected", "selected");
}
dataElement.append(optionElement);
@@ -93,34 +91,34 @@ function promptCreateSelect() {
}
function promptRegister() {
- promptId = document.location.hash.replace('#', '');
+ promptId = document.location.hash.replace("#", "");
try {
- promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId));
+ promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
} catch (error) {
return promptError(error);
}
if (promptOptions.useHtmlLabel) {
- document.querySelector('#label').innerHTML = promptOptions.label;
+ document.querySelector("#label").innerHTML = promptOptions.label;
} else {
- document.querySelector('#label').textContent = promptOptions.label;
+ document.querySelector("#label").textContent = promptOptions.label;
}
if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
- document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok;
+ document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
}
if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
- document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel;
+ document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
}
if (promptOptions.customStylesheet) {
try {
const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
if (customStyleContent) {
- const customStyle = document.createElement('style');
- customStyle.setAttribute('rel', 'stylesheet');
+ const customStyle = document.createElement("style");
+ customStyle.setAttribute("rel", "stylesheet");
customStyle.append(document.createTextNode(customStyleContent));
document.head.append(customStyle);
}
@@ -129,25 +127,25 @@ function promptRegister() {
}
}
- document.querySelector('#form').addEventListener('submit', promptSubmit);
- document.querySelector('#cancel').addEventListener('click', promptCancel);
+ document.querySelector("#form").addEventListener("submit", promptSubmit);
+ document.querySelector("#cancel").addEventListener("click", promptCancel);
- const dataContainerElement = document.querySelector('#data-container');
+ const dataContainerElement = document.querySelector("#data-container");
let dataElement;
- if (promptOptions.type === 'input') {
+ if (promptOptions.type === "input") {
dataElement = promptCreateInput();
- } else if (promptOptions.type === 'select') {
+ } else if (promptOptions.type === "select") {
dataElement = promptCreateSelect();
} else {
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
dataContainerElement.append(dataElement);
- dataElement.setAttribute('id', 'data');
+ dataElement.setAttribute("id", "data");
dataElement.focus();
- if (promptOptions.type === 'input') {
+ if (promptOptions.type === "input") {
dataElement.select();
}
@@ -161,10 +159,10 @@ function promptRegister() {
}
}
-window.addEventListener('error', error => {
+window.addEventListener("error", error => {
if (promptId) {
- promptError('An error has occured on the prompt window: \n' + error);
+ promptError("An error has occured on the prompt window: \n" + error);
}
});
-docReady(promptRegister);
\ No newline at end of file
+docReady(promptRegister);
From 0e9b15722a02fc1e423fb0d5eec4cd969d397dae Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Tue, 6 Apr 2021 01:30:47 +0300
Subject: [PATCH 26/52] add inline doc
---
index.js | 18 ++--
menu.js | 1 +
providers/logger.js | 20 ++--
providers/prompt/index.js | 41 +++++---
providers/prompt/page/prompt.js | 168 ++++++++++++++++++--------------
providers/prompt/readme.md | 5 +-
6 files changed, 148 insertions(+), 105 deletions(-)
diff --git a/index.js b/index.js
index 9e8b7233..7fd88754 100644
--- a/index.js
+++ b/index.js
@@ -110,8 +110,8 @@ function createMainWindow() {
titleBarStyle: useInlineMenu
? "hidden"
: is.macOS()
- ? "hiddenInset"
- : "default",
+ ? "hiddenInset"
+ : "default",
autoHideMenuBar: config.get("options.hideMenu"),
});
if (windowPosition) {
@@ -156,7 +156,7 @@ function createMainWindow() {
let createdWindow = false;
app.on("browser-window-created", (event, win) => {
- //Ensure listeners aren't registered when creating input dialog
+ //Ensures listeners are registered only once
if (createdWindow) {
return;
}
@@ -172,7 +172,7 @@ app.on("browser-window-created", (event, win) => {
frameProcessId,
frameRoutingId,
) => {
- let log = {
+ const log = {
error: "did-fail-load",
event,
errorCode,
@@ -183,7 +183,7 @@ app.on("browser-window-created", (event, win) => {
frameRoutingId,
};
if (is.dev()) {
- console.log(log);
+ console.log(log.toString());
}
win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
@@ -306,13 +306,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;
});
diff --git a/menu.js b/menu.js
index c0495d68..21ac1e7a 100644
--- a/menu.js
+++ b/menu.js
@@ -12,6 +12,7 @@ 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) {
diff --git a/providers/logger.js b/providers/logger.js
index 08a940f3..730a3dfa 100644
--- a/providers/logger.js
+++ b/providers/logger.js
@@ -1,11 +1,15 @@
const { ipcRenderer } = require("electron");
+function logToString(log) {
+ let string = (typeof log === "string") ? log : log.toString();
+ if (!string || string.includes("[object Object]")) {
+ string = JSON.stringify(log);
+ }
+ return string;
+}
+
module.exports = () => {
- ipcRenderer.on("log", (event, log) => {
- let string = log || log.toString();
- if (!string || string === "[object Object]") {
- string = JSON.stringify(log);
- }
- console.log(string);
- })
-};
\ No newline at end of file
+ ipcRenderer.on("log", (event, log) => {
+ console.log(logToString(log));
+ });
+};
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 302eeea0..bbba8b78 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -10,8 +10,10 @@ const DEFAULT_HEIGHT = 160;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
+ //id used to ensure unique listeners per window
const id = `${Date.now()}-${Math.random()}`;
+ //custom options override default
const options_ = Object.assign(
{
width: DEFAULT_WIDTH,
@@ -19,12 +21,12 @@ function electronPrompt(options, parentWindow) {
minWidth: DEFAULT_WIDTH,
minHeight: DEFAULT_HEIGHT,
resizable: false,
- title: 'Prompt',
- label: 'Please input a value:',
+ title: "Prompt",
+ label: "Please input a value:",
buttonLabels: null,
alwaysOnTop: false,
value: null,
- type: 'input',
+ type: "input",
selectOptions: null,
icon: null,
useHtmlLabel: false,
@@ -70,10 +72,7 @@ function electronPrompt(options, parentWindow) {
promptWindow.setMenu(null);
promptWindow.setMenuBarVisibility(options_.menuBarVisible);
- const getOptionsListener = event => {
- event.returnValue = JSON.stringify(options_);
- };
-
+ //called on exit
const cleanup = () => {
ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener);
ipcMain.removeListener("prompt-post-data:" + id, postDataListener);
@@ -85,6 +84,12 @@ function electronPrompt(options, parentWindow) {
}
};
+ ///transfer options to front
+ const getOptionsListener = event => {
+ event.returnValue = JSON.stringify(options_);
+ };
+
+ //get input from front
const postDataListener = (event, value) => {
resolve(value);
event.returnValue = null;
@@ -96,12 +101,14 @@ function electronPrompt(options, parentWindow) {
cleanup();
};
+ //get error from front
const errorListener = (event, message) => {
reject(new Error(message));
event.returnValue = null;
cleanup();
};
+ //attach listeners
ipcMain.on("prompt-get-options:" + id, getOptionsListener);
ipcMain.on("prompt-post-data:" + id, postDataListener);
ipcMain.on("prompt-error:" + id, errorListener);
@@ -113,13 +120,23 @@ function electronPrompt(options, parentWindow) {
resolve(null);
});
- const promptUrl = url.format({
- protocol: "file",
- slashes: true,
- pathname: path.join(__dirname, "page", "prompt.html"),
- hash: id
+ //should never happen
+ promptWindow.webContents.on("did-fail-load", (
+ event,
+ errorCode,
+ errorDescription,
+ validatedURL,
+ ) => {
+ const log = {
+ error: "did-fail-load",
+ errorCode,
+ errorDescription,
+ validatedURL,
+ };
+ reject(new Error("prompt.html did-fail-load, log:\n", + log.toString()));
});
+ //Finally, load prompt
promptWindow.loadURL(promptUrl);
});
}
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 67acd31d..b7a54120 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -5,6 +5,93 @@ const docReady = require("doc-ready");
let promptId = null;
let promptOptions = null;
+
+docReady(promptRegister);
+//start here
+function promptRegister() {
+ //get custom session id
+ promptId = document.location.hash.replace("#", "");
+
+ //get options from back
+ try {
+ promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
+ } catch (error) {
+ return promptError(error);
+ }
+
+ //set label
+ if (promptOptions.useHtmlLabel) {
+ document.querySelector("#label").innerHTML = promptOptions.label;
+ } else {
+ document.querySelector("#label").textContent = promptOptions.label;
+ }
+
+ //set button label
+ if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
+ document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
+ }
+
+ if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
+ document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
+ }
+
+ //inject custom stylesheet from options
+ if (promptOptions.customStylesheet) {
+ try {
+ const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
+ if (customStyleContent) {
+ const customStyle = document.createElement("style");
+ customStyle.setAttribute("rel", "stylesheet");
+ customStyle.append(document.createTextNode(customStyleContent));
+ document.head.append(customStyle);
+ }
+ } catch (error) {
+ return promptError(error);
+ }
+ }
+
+ //add button listeners
+ document.querySelector("#form").addEventListener("submit", promptSubmit);
+ document.querySelector("#cancel").addEventListener("click", promptCancel);
+
+
+ //create input/select
+ const dataContainerElement = document.querySelector("#data-container");
+ let dataElement;
+ if (promptOptions.type === "input") {
+ dataElement = promptCreateInput();
+ } else if (promptOptions.type === "select") {
+ dataElement = promptCreateSelect();
+ } else {
+ return promptError(`Unhandled input type '${promptOptions.type}'`);
+ }
+
+ dataContainerElement.append(dataElement);
+ dataElement.setAttribute("id", "data");
+
+ dataElement.focus();
+ if (promptOptions.type === "input") {
+ dataElement.select();
+ }
+
+ //load custom script from options
+ if (promptOptions.customScript) {
+ try {
+ const customScript = require(promptOptions.customScript);
+ customScript();
+ } catch (error) {
+ return promptError(error);
+ }
+ }
+}
+
+window.addEventListener("error", error => {
+ if (promptId) {
+ promptError("An error has occured on the prompt window: \n" + error);
+ }
+});
+
+//send error to back
function promptError(error) {
if (error instanceof Error) {
error = error.message;
@@ -13,10 +100,12 @@ function promptError(error) {
ipcRenderer.sendSync("prompt-error:" + promptId, error);
}
+//send to back: input=null
function promptCancel() {
ipcRenderer.sendSync("prompt-post-data:" + promptId, null);
}
+//transfer input data to back
function promptSubmit() {
const dataElement = document.querySelector("#data");
let data = null;
@@ -32,6 +121,7 @@ function promptSubmit() {
ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
}
+//creates input box
function promptCreateInput() {
const dataElement = document.createElement("input");
dataElement.setAttribute("type", "text");
@@ -42,6 +132,7 @@ function promptCreateInput() {
dataElement.value = "";
}
+ //insert custom input attributes if in options
if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") {
for (const k in promptOptions.inputAttrs) {
if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
@@ -52,12 +143,14 @@ function promptCreateInput() {
}
}
+ //Cancel/Exit on 'Escape'
dataElement.addEventListener("keyup", event => {
if (event.key === "Escape") {
promptCancel();
}
});
+ //Confrim on 'Enter'
dataElement.addEventListener("keypress", event => {
if (event.key === "Enter") {
event.preventDefault();
@@ -68,6 +161,7 @@ function promptCreateInput() {
return dataElement;
}
+//create multiple select
function promptCreateSelect() {
const dataElement = document.createElement("select");
let optionElement;
@@ -90,79 +184,5 @@ function promptCreateSelect() {
return dataElement;
}
-function promptRegister() {
- promptId = document.location.hash.replace("#", "");
- try {
- promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
- } catch (error) {
- return promptError(error);
- }
- if (promptOptions.useHtmlLabel) {
- document.querySelector("#label").innerHTML = promptOptions.label;
- } else {
- document.querySelector("#label").textContent = promptOptions.label;
- }
-
- if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
- document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
- }
-
- if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
- document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
- }
-
- if (promptOptions.customStylesheet) {
- try {
- const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
- if (customStyleContent) {
- const customStyle = document.createElement("style");
- customStyle.setAttribute("rel", "stylesheet");
- customStyle.append(document.createTextNode(customStyleContent));
- document.head.append(customStyle);
- }
- } catch (error) {
- return promptError(error);
- }
- }
-
- document.querySelector("#form").addEventListener("submit", promptSubmit);
- document.querySelector("#cancel").addEventListener("click", promptCancel);
-
- const dataContainerElement = document.querySelector("#data-container");
-
- let dataElement;
- if (promptOptions.type === "input") {
- dataElement = promptCreateInput();
- } else if (promptOptions.type === "select") {
- dataElement = promptCreateSelect();
- } else {
- return promptError(`Unhandled input type '${promptOptions.type}'`);
- }
-
- dataContainerElement.append(dataElement);
- dataElement.setAttribute("id", "data");
-
- dataElement.focus();
- if (promptOptions.type === "input") {
- dataElement.select();
- }
-
- if (promptOptions.customScript) {
- try {
- const customScript = require(promptOptions.customScript);
- customScript();
- } catch (error) {
- return promptError(error);
- }
- }
-}
-
-window.addEventListener("error", error => {
- if (promptId) {
- promptError("An error has occured on the prompt window: \n" + error);
- }
-});
-
-docReady(promptRegister);
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
index 2eb13b74..6683aced 100644
--- a/providers/prompt/readme.md
+++ b/providers/prompt/readme.md
@@ -3,11 +3,14 @@
## Usage
-
```js
prompt([options, parentBrowserWindow]).then(...).catch(...)
```
+Promise resolve returns input
+If user presses cancel/exit window, input = null;
+
+On error, Prompise reject returns custom error message
## Example
```js
From 17fd499420486cdb4d77ec5d8387df8f692bcbbe Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Tue, 6 Apr 2021 01:51:11 +0300
Subject: [PATCH 27/52] fix typo
---
menu.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/menu.js b/menu.js
index 21ac1e7a..90487970 100644
--- a/menu.js
+++ b/menu.js
@@ -338,10 +338,10 @@ function setProxy(item, win) {
.then((input) => {
if (input !== null && input !== example) {
config.set("options.proxy", input);
- item.checked = (input === "") ? false : true;
+ item.checked = input !== "";
} else { //user pressed cancel
item.checked = !item.checked; //reset checkbox
}
})
.catch(console.error);
-}
\ No newline at end of file
+}
From 980ffb45e927335b66ab950751707e283be48674 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Tue, 6 Apr 2021 21:57:16 +0300
Subject: [PATCH 28/52] Create readme.md
refactor and css fix
xo --fix
add inline doc
fix typo
---
index.js | 18 +-
menu.js | 9 +-
package.json | 12 +-
plugins/in-app-menu/back.js | 9 +-
providers/logger.js | 20 +-
providers/prompt/custom-titlebar.js | 14 ++
providers/prompt/customTitlebar.js | 19 --
.../{darkPrompt.css => dark-prompt.css} | 4 +-
providers/prompt/index.js | 73 +++---
providers/prompt/page/prompt.js | 232 ++++++++++--------
providers/prompt/readme.md | 79 ++++++
11 files changed, 306 insertions(+), 183 deletions(-)
create mode 100644 providers/prompt/custom-titlebar.js
delete mode 100644 providers/prompt/customTitlebar.js
rename providers/prompt/{darkPrompt.css => dark-prompt.css} (94%)
create mode 100644 providers/prompt/readme.md
diff --git a/index.js b/index.js
index 9e8b7233..7fd88754 100644
--- a/index.js
+++ b/index.js
@@ -110,8 +110,8 @@ function createMainWindow() {
titleBarStyle: useInlineMenu
? "hidden"
: is.macOS()
- ? "hiddenInset"
- : "default",
+ ? "hiddenInset"
+ : "default",
autoHideMenuBar: config.get("options.hideMenu"),
});
if (windowPosition) {
@@ -156,7 +156,7 @@ function createMainWindow() {
let createdWindow = false;
app.on("browser-window-created", (event, win) => {
- //Ensure listeners aren't registered when creating input dialog
+ //Ensures listeners are registered only once
if (createdWindow) {
return;
}
@@ -172,7 +172,7 @@ app.on("browser-window-created", (event, win) => {
frameProcessId,
frameRoutingId,
) => {
- let log = {
+ const log = {
error: "did-fail-load",
event,
errorCode,
@@ -183,7 +183,7 @@ app.on("browser-window-created", (event, win) => {
frameRoutingId,
};
if (is.dev()) {
- console.log(log);
+ console.log(log.toString());
}
win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
@@ -306,13 +306,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;
});
diff --git a/menu.js b/menu.js
index 3754d14c..90487970 100644
--- a/menu.js
+++ b/menu.js
@@ -12,6 +12,7 @@ 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) {
@@ -321,13 +322,13 @@ function setProxy(item, win) {
},
type: 'input',
icon: iconPath,
- customStylesheet: path.join(__dirname, "providers", "prompt", "darkPrompt.css"),
+ customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"),
};
//TODO: custom bar on prompt need testing on macOS
if(!is.macOS()) {
Object.assign(options, {
frame: false,
- customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"),
+ customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"),
enableRemoteModule: true,
height: 200,
width: 450,
@@ -337,10 +338,10 @@ function setProxy(item, win) {
.then((input) => {
if (input !== null && input !== example) {
config.set("options.proxy", input);
- item.checked = (input === "") ? false : true;
+ item.checked = input !== "";
} else { //user pressed cancel
item.checked = !item.checked; //reset checkbox
}
})
.catch(console.error);
-}
\ No newline at end of file
+}
diff --git a/package.json b/package.json
index 36591897..144ac53f 100644
--- a/package.json
+++ b/package.json
@@ -101,6 +101,16 @@
"envs": [
"node",
"browser"
- ]
+ ],
+ "rules": {
+ "quotes": [
+ "error",
+ "double",
+ {
+ "avoidEscape": true,
+ "allowTemplateLiterals": true
+ }
+ ]
+ }
}
}
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index b17ee032..938c5475 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -9,8 +9,6 @@ const { injectCSS } = require("../utils");
//check that menu doesn't get created twice
let calledReadyToShow = false;
-//check menu state isn't changed twice
-let calledFinishedLoad = false
//tracks menu visibility
let visible = true;
// win hook for fixing menu
@@ -37,6 +35,7 @@ module.exports = (winImport) => {
if (calledReadyToShow) {
return;
}
+
calledReadyToShow = true;
setApplicationMenu(win);
@@ -53,7 +52,7 @@ module.exports = (winImport) => {
win.webContents.on("did-finish-load", () => {
// fix bug with menu not applying on start when no internet connection available
setMenuVisibility(!config.get("options.hideMenu"));
- })
+ });
};
function switchMenuVisibility() {
@@ -81,10 +80,10 @@ 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);
- updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu);
+ updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu);
};
item.fixed = true;
}
diff --git a/providers/logger.js b/providers/logger.js
index 08a940f3..730a3dfa 100644
--- a/providers/logger.js
+++ b/providers/logger.js
@@ -1,11 +1,15 @@
const { ipcRenderer } = require("electron");
+function logToString(log) {
+ let string = (typeof log === "string") ? log : log.toString();
+ if (!string || string.includes("[object Object]")) {
+ string = JSON.stringify(log);
+ }
+ return string;
+}
+
module.exports = () => {
- ipcRenderer.on("log", (event, log) => {
- let string = log || log.toString();
- if (!string || string === "[object Object]") {
- string = JSON.stringify(log);
- }
- console.log(string);
- })
-};
\ No newline at end of file
+ ipcRenderer.on("log", (event, log) => {
+ console.log(logToString(log));
+ });
+};
diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js
new file mode 100644
index 00000000..c36ce5f5
--- /dev/null
+++ b/providers/prompt/custom-titlebar.js
@@ -0,0 +1,14 @@
+const customTitlebar = require("custom-electron-titlebar");
+
+module.exports = () => {
+ const bar = new customTitlebar.Titlebar({
+ backgroundColor: customTitlebar.Color.fromHex("#050505"),
+ minimizable: false,
+ maximizable: false,
+ menu: null
+ });
+ const mainStyle = document.querySelector("#container").style;
+ mainStyle.width = "100%";
+ mainStyle.position = "fixed";
+ mainStyle.border = "unset";
+};
diff --git a/providers/prompt/customTitlebar.js b/providers/prompt/customTitlebar.js
deleted file mode 100644
index 116aa56c..00000000
--- a/providers/prompt/customTitlebar.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const customTitlebar = require("custom-electron-titlebar");
-
-module.exports = () => {
- const bar = new customTitlebar.Titlebar({
- backgroundColor: customTitlebar.Color.fromHex("#050505"),
- minimizable: false,
- maximizable: false,
- unfocusEffect: true,
- });
- try {
- bar.updateMenu(null);
- } catch (e) {
- //will always throw type error - null isn't menu, but it works
- }
- let container = document.querySelector('#container');
- container.style.width = '100%';
- container.style.position = 'fixed';
- container.style.border = 'unset';
-}
\ No newline at end of file
diff --git a/providers/prompt/darkPrompt.css b/providers/prompt/dark-prompt.css
similarity index 94%
rename from providers/prompt/darkPrompt.css
rename to providers/prompt/dark-prompt.css
index 8b343a25..49e0f88e 100644
--- a/providers/prompt/darkPrompt.css
+++ b/providers/prompt/dark-prompt.css
@@ -34,7 +34,9 @@ body {
}
#ok:hover,
-#cancel:hover {
+#ok:focus,
+#cancel:hover,
+#cancel:focus {
outline: rgba(60, 0, 0, 0.4) solid 2px;
}
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index d6664305..bbba8b78 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -1,17 +1,19 @@
-const electron = require('electron');
+const electron = require("electron");
const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;
const ipcMain = electron.ipcMain || electron.remote.ipcMain;
-const url = require('url');
-const path = require('path');
+const url = require("url");
+const path = require("path");
const DEFAULT_WIDTH = 370;
const DEFAULT_HEIGHT = 160;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
+ //id used to ensure unique listeners per window
const id = `${Date.now()}-${Math.random()}`;
+ //custom options override default
const options_ = Object.assign(
{
width: DEFAULT_WIDTH,
@@ -19,12 +21,12 @@ function electronPrompt(options, parentWindow) {
minWidth: DEFAULT_WIDTH,
minHeight: DEFAULT_HEIGHT,
resizable: false,
- title: 'Prompt',
- label: 'Please input a value:',
+ title: "Prompt",
+ label: "Please input a value:",
buttonLabels: null,
alwaysOnTop: false,
value: null,
- type: 'input',
+ type: "input",
selectOptions: null,
icon: null,
useHtmlLabel: false,
@@ -38,7 +40,7 @@ function electronPrompt(options, parentWindow) {
options || {}
);
- if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) {
+ if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
reject(new Error('"selectOptions" must be an object'));
return;
}
@@ -50,9 +52,9 @@ function electronPrompt(options, parentWindow) {
minWidth: options_.minWidth,
minHeight: options_.minHeight,
resizable: options_.resizable,
- minimizable: false,
- fullscreenable: false,
- maximizable: false,
+ minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop,
+ fullscreenable: options_.resizable,
+ maximizable: options_.resizable,
parent: parentWindow,
skipTaskbar: options_.skipTaskbar,
alwaysOnTop: options_.alwaysOnTop,
@@ -70,14 +72,11 @@ function electronPrompt(options, parentWindow) {
promptWindow.setMenu(null);
promptWindow.setMenuBarVisibility(options_.menuBarVisible);
- const getOptionsListener = event => {
- event.returnValue = JSON.stringify(options_);
- };
-
+ //called on exit
const cleanup = () => {
- ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener);
- ipcMain.removeListener('prompt-post-data:' + id, postDataListener);
- ipcMain.removeListener('prompt-error:' + id, errorListener);
+ ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener);
+ ipcMain.removeListener("prompt-post-data:" + id, postDataListener);
+ ipcMain.removeListener("prompt-error:" + id, errorListener);
if (promptWindow) {
promptWindow.close();
@@ -85,6 +84,12 @@ function electronPrompt(options, parentWindow) {
}
};
+ ///transfer options to front
+ const getOptionsListener = event => {
+ event.returnValue = JSON.stringify(options_);
+ };
+
+ //get input from front
const postDataListener = (event, value) => {
resolve(value);
event.returnValue = null;
@@ -92,34 +97,46 @@ function electronPrompt(options, parentWindow) {
};
const unresponsiveListener = () => {
- reject(new Error('Window was unresponsive'));
+ reject(new Error("Window was unresponsive"));
cleanup();
};
+ //get error from front
const errorListener = (event, message) => {
reject(new Error(message));
event.returnValue = null;
cleanup();
};
- ipcMain.on('prompt-get-options:' + id, getOptionsListener);
- ipcMain.on('prompt-post-data:' + id, postDataListener);
- ipcMain.on('prompt-error:' + id, errorListener);
- promptWindow.on('unresponsive', unresponsiveListener);
+ //attach listeners
+ ipcMain.on("prompt-get-options:" + id, getOptionsListener);
+ ipcMain.on("prompt-post-data:" + id, postDataListener);
+ ipcMain.on("prompt-error:" + id, errorListener);
+ promptWindow.on("unresponsive", unresponsiveListener);
- promptWindow.on('closed', () => {
+ promptWindow.on("closed", () => {
promptWindow = null;
cleanup();
resolve(null);
});
- const promptUrl = url.format({
- protocol: 'file',
- slashes: true,
- pathname: path.join(__dirname, 'page', 'prompt.html'),
- hash: id
+ //should never happen
+ promptWindow.webContents.on("did-fail-load", (
+ event,
+ errorCode,
+ errorDescription,
+ validatedURL,
+ ) => {
+ const log = {
+ error: "did-fail-load",
+ errorCode,
+ errorDescription,
+ validatedURL,
+ };
+ reject(new Error("prompt.html did-fail-load, log:\n", + log.toString()));
});
+ //Finally, load prompt
promptWindow.loadURL(promptUrl);
});
}
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 754d0e74..b7a54120 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -1,126 +1,47 @@
-const fs = require('fs');
-const {ipcRenderer} = require('electron');
-const docReady = require('doc-ready');
+const fs = require("fs");
+const {ipcRenderer} = require("electron");
+const docReady = require("doc-ready");
let promptId = null;
let promptOptions = null;
-function promptError(error) {
- if (error instanceof Error) {
- error = error.message;
- }
-
- ipcRenderer.sendSync('prompt-error:' + promptId, error);
-}
-
-function promptCancel() {
- ipcRenderer.sendSync('prompt-post-data:' + promptId, null);
-}
-
-function promptSubmit() {
- const dataElement = document.querySelector('#data');
- let data = null;
-
- if (promptOptions.type === 'input') {
- data = dataElement.value;
- } else if (promptOptions.type === 'select') {
- if (promptOptions.selectMultiple) {
- data = dataElement.querySelectorAll('option[selected]').map(o => o.getAttribute('value'));
- } else {
- data = dataElement.value;
- }
- }
-
- ipcRenderer.sendSync('prompt-post-data:' + promptId, data);
-}
-
-function promptCreateInput() {
- const dataElement = document.createElement('input');
- dataElement.setAttribute('type', 'text');
-
- if (promptOptions.value) {
- dataElement.value = promptOptions.value;
- } else {
- dataElement.value = '';
- }
-
- if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === 'object') {
- for (const k in promptOptions.inputAttrs) {
- if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
- continue;
- }
-
- dataElement.setAttribute(k, promptOptions.inputAttrs[k]);
- }
- }
-
- dataElement.addEventListener('keyup', event => {
- if (event.key === 'Escape') {
- promptCancel();
- }
- });
-
- dataElement.addEventListener('keypress', event => {
- if (event.key === 'Enter') {
- event.preventDefault();
- document.querySelector('#ok').click();
- }
- });
-
- return dataElement;
-}
-
-function promptCreateSelect() {
- const dataElement = document.createElement('select');
- let optionElement;
-
- for (const k in promptOptions.selectOptions) {
- if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) {
- continue;
- }
-
- optionElement = document.createElement('option');
- optionElement.setAttribute('value', k);
- optionElement.textContent = promptOptions.selectOptions[k];
- if (k === promptOptions.value) {
- optionElement.setAttribute('selected', 'selected');
- }
-
- dataElement.append(optionElement);
- }
-
- return dataElement;
-}
+docReady(promptRegister);
+//start here
function promptRegister() {
- promptId = document.location.hash.replace('#', '');
+ //get custom session id
+ promptId = document.location.hash.replace("#", "");
+ //get options from back
try {
- promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId));
+ promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
} catch (error) {
return promptError(error);
}
+ //set label
if (promptOptions.useHtmlLabel) {
- document.querySelector('#label').innerHTML = promptOptions.label;
+ document.querySelector("#label").innerHTML = promptOptions.label;
} else {
- document.querySelector('#label').textContent = promptOptions.label;
+ document.querySelector("#label").textContent = promptOptions.label;
}
+ //set button label
if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
- document.querySelector('#ok').textContent = promptOptions.buttonLabels.ok;
+ document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
}
if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
- document.querySelector('#cancel').textContent = promptOptions.buttonLabels.cancel;
+ document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
}
+ //inject custom stylesheet from options
if (promptOptions.customStylesheet) {
try {
const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
if (customStyleContent) {
- const customStyle = document.createElement('style');
- customStyle.setAttribute('rel', 'stylesheet');
+ const customStyle = document.createElement("style");
+ customStyle.setAttribute("rel", "stylesheet");
customStyle.append(document.createTextNode(customStyleContent));
document.head.append(customStyle);
}
@@ -129,28 +50,31 @@ function promptRegister() {
}
}
- document.querySelector('#form').addEventListener('submit', promptSubmit);
- document.querySelector('#cancel').addEventListener('click', promptCancel);
+ //add button listeners
+ document.querySelector("#form").addEventListener("submit", promptSubmit);
+ document.querySelector("#cancel").addEventListener("click", promptCancel);
- const dataContainerElement = document.querySelector('#data-container');
+ //create input/select
+ const dataContainerElement = document.querySelector("#data-container");
let dataElement;
- if (promptOptions.type === 'input') {
+ if (promptOptions.type === "input") {
dataElement = promptCreateInput();
- } else if (promptOptions.type === 'select') {
+ } else if (promptOptions.type === "select") {
dataElement = promptCreateSelect();
} else {
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
dataContainerElement.append(dataElement);
- dataElement.setAttribute('id', 'data');
+ dataElement.setAttribute("id", "data");
dataElement.focus();
- if (promptOptions.type === 'input') {
+ if (promptOptions.type === "input") {
dataElement.select();
}
+ //load custom script from options
if (promptOptions.customScript) {
try {
const customScript = require(promptOptions.customScript);
@@ -161,10 +85,104 @@ function promptRegister() {
}
}
-window.addEventListener('error', error => {
+window.addEventListener("error", error => {
if (promptId) {
- promptError('An error has occured on the prompt window: \n' + error);
+ promptError("An error has occured on the prompt window: \n" + error);
}
});
-docReady(promptRegister);
\ No newline at end of file
+//send error to back
+function promptError(error) {
+ if (error instanceof Error) {
+ error = error.message;
+ }
+
+ ipcRenderer.sendSync("prompt-error:" + promptId, error);
+}
+
+//send to back: input=null
+function promptCancel() {
+ ipcRenderer.sendSync("prompt-post-data:" + promptId, null);
+}
+
+//transfer input data to back
+function promptSubmit() {
+ const dataElement = document.querySelector("#data");
+ let data = null;
+
+ if (promptOptions.type === "input") {
+ data = dataElement.value;
+ } else if (promptOptions.type === "select") {
+ data = promptOptions.selectMultiple ?
+ dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
+ dataElement.value;
+ }
+
+ ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
+}
+
+//creates input box
+function promptCreateInput() {
+ const dataElement = document.createElement("input");
+ dataElement.setAttribute("type", "text");
+
+ if (promptOptions.value) {
+ dataElement.value = promptOptions.value;
+ } else {
+ dataElement.value = "";
+ }
+
+ //insert custom input attributes if in options
+ if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") {
+ for (const k in promptOptions.inputAttrs) {
+ if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
+ continue;
+ }
+
+ dataElement.setAttribute(k, promptOptions.inputAttrs[k]);
+ }
+ }
+
+ //Cancel/Exit on 'Escape'
+ dataElement.addEventListener("keyup", event => {
+ if (event.key === "Escape") {
+ promptCancel();
+ }
+ });
+
+ //Confrim on 'Enter'
+ dataElement.addEventListener("keypress", event => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ document.querySelector("#ok").click();
+ }
+ });
+
+ return dataElement;
+}
+
+//create multiple select
+function promptCreateSelect() {
+ const dataElement = document.createElement("select");
+ let optionElement;
+
+ for (const k in promptOptions.selectOptions) {
+ if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) {
+ continue;
+ }
+
+ optionElement = document.createElement("option");
+ optionElement.setAttribute("value", k);
+ optionElement.textContent = promptOptions.selectOptions[k];
+ if (k === promptOptions.value) {
+ optionElement.setAttribute("selected", "selected");
+ }
+
+ dataElement.append(optionElement);
+ }
+
+ return dataElement;
+}
+
+
+
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
new file mode 100644
index 00000000..6683aced
--- /dev/null
+++ b/providers/prompt/readme.md
@@ -0,0 +1,79 @@
+# Prompt Documentation
+
+
+
+## Usage
+```js
+prompt([options, parentBrowserWindow]).then(...).catch(...)
+```
+Promise resolve returns input
+
+If user presses cancel/exit window, input = null;
+
+On error, Prompise reject returns custom error message
+## Example
+
+```js
+const prompt = require('./providers/prompt');
+
+prompt({
+ title: 'Prompt example',
+ label: 'URL:',
+ value: 'http://example.org',
+ inputAttrs: {
+ type: 'url'
+ },
+ type: 'input'
+})
+.then((r) => {
+ if(r === null) {
+ console.log('user cancelled');
+ } else {
+ console.log('result', r);
+ }
+})
+.catch(console.error);
+```
+
+### Options object (optional)
+
+| Key | Explanation |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. |
+| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. |
+| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. |
+| value | (optional, string) The default value for the input field. Defaults to null. |
+| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. |
+| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input' |
+| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
+| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
+| width | (optional, integer) The width of the prompt window. Defaults to 370. |
+| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. |
+| height | (optional, integer) The height of the prompt window. Defaults to 130. |
+| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. |
+| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. |
+| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false |
+| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. |
+| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. |
+| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. |
+| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. |
+| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. |
+| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. |
+| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. |
+
+If not supplied, it uses the defaults listed in the table above.
+
+### parentBrowserWindow (optional)
+
+The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null.
+
+### customScript (optional)
+
+Create the script with the following template:
+
+```node
+module.exports = () => {
+ // This function will be called as a preload script
+ // So you can use front features like `document.querySelector`
+};
+```
From 80b12076406e5e06a219f5b7824f1f3821b54832 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Fri, 9 Apr 2021 02:19:06 +0300
Subject: [PATCH 29/52] fix rare crash due to unfocus effect
---
plugins/in-app-menu/front.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js
index 3287dc5d..8ee1c9cf 100644
--- a/plugins/in-app-menu/front.js
+++ b/plugins/in-app-menu/front.js
@@ -6,6 +6,8 @@ module.exports = () => {
const bar = new customTitlebar.Titlebar({
backgroundColor: customTitlebar.Color.fromHex("#050505"),
itemBackgroundColor: customTitlebar.Color.fromHex("#121212"),
+ // !important - unfocus effect can sometimes cause crash as of v3.2.6 of custom-electron-titlebar
+ unfocusEffect: false
});
bar.updateTitle(" ");
document.title = "Youtube Music";
From 3d41d04818ef355cd912e4e6ec7adad081854733 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Fri, 9 Apr 2021 22:28:55 +0300
Subject: [PATCH 30/52] Revert "fix rare crash due to unfocus effect"
This reverts commit 80b12076406e5e06a219f5b7824f1f3821b54832.
---
plugins/in-app-menu/front.js | 2 --
1 file changed, 2 deletions(-)
diff --git a/plugins/in-app-menu/front.js b/plugins/in-app-menu/front.js
index 8ee1c9cf..3287dc5d 100644
--- a/plugins/in-app-menu/front.js
+++ b/plugins/in-app-menu/front.js
@@ -6,8 +6,6 @@ module.exports = () => {
const bar = new customTitlebar.Titlebar({
backgroundColor: customTitlebar.Color.fromHex("#050505"),
itemBackgroundColor: customTitlebar.Color.fromHex("#121212"),
- // !important - unfocus effect can sometimes cause crash as of v3.2.6 of custom-electron-titlebar
- unfocusEffect: false
});
bar.updateTitle(" ");
document.title = "Youtube Music";
From 09d9f72db289aff51c20fd83538fbb40b3ee652c Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sat, 10 Apr 2021 02:51:38 +0300
Subject: [PATCH 31/52] add unresponsive listener
---
index.js | 44 ++++++++++++++++++++-----
plugins/in-app-menu/back.js | 10 +-----
preload.js | 2 +-
providers/{logger.js => frontLogger.js} | 2 +-
4 files changed, 39 insertions(+), 19 deletions(-)
rename providers/{logger.js => frontLogger.js} (87%)
diff --git a/index.js b/index.js
index 7fd88754..addd98ed 100644
--- a/index.js
+++ b/index.js
@@ -2,6 +2,7 @@
const path = require("path");
const electron = require("electron");
+const { dialog } = require("electron");
const is = require("electron-is");
const unhandled = require("electron-unhandled");
const { autoUpdater } = require("electron-updater");
@@ -144,7 +145,11 @@ 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();
@@ -154,13 +159,7 @@ function createMainWindow() {
return win;
}
-let createdWindow = false;
-app.on("browser-window-created", (event, win) => {
- //Ensures listeners are registered only once
- if (createdWindow) {
- return;
- }
- createdWindow = true;
+app.once("browser-window-created", (event, win) => {
loadPlugins(win);
win.webContents.on("did-fail-load", (
@@ -325,3 +324,32 @@ app.on("ready", () => {
});
}
});
+
+function showUnresponsiveDialog(win, details) {
+ if (!!details) {
+ console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t"))
+ }
+ dialog.showMessageBox(win, {
+ type: "error",
+ title: "Window Unresponsive",
+ message: "The Application is Unresponsive",
+ details: "We are sorry for the inconveniance! please choose what to do with the application:",
+ buttons: ["Wait", "Relaunch", "Quit"],
+ cancelId: 0
+ }).then( response => {
+ switch (response) {
+ case 1: //if relaunch - relaunch+exit
+ app.relaunch();
+ case 2:
+ app.exit();
+ break;
+ case 0:
+ default:
+ return;
+ //maybe set a timer and afterwards check responsivness and call function again if failed
+ }
+ });
+}
+
+module.exports.aDialog = showUnresponsiveDialog;
+
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 938c5475..8365ac8b 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -7,8 +7,6 @@ const config = require("../../config");
const { setApplicationMenu } = require("../../menu");
const { injectCSS } = require("../utils");
-//check that menu doesn't get created twice
-let calledReadyToShow = false;
//tracks menu visibility
let visible = true;
// win hook for fixing menu
@@ -30,13 +28,7 @@ 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 (calledReadyToShow) {
- return;
- }
-
- calledReadyToShow = true;
+ win.once("ready-to-show", () => {
setApplicationMenu(win);
diff --git a/preload.js b/preload.js
index f25dd6b7..5fcb2e07 100644
--- a/preload.js
+++ b/preload.js
@@ -34,7 +34,7 @@ document.addEventListener("DOMContentLoaded", () => {
fileExists(songInfoProviderPath, require(songInfoProviderPath));
// inject front logger
- const loggerPath = path.join(__dirname, "providers", "logger.js")
+ const loggerPath = path.join(__dirname, "providers", "frontLogger.js")
fileExists(loggerPath, require(loggerPath));
// Add action for reloading
diff --git a/providers/logger.js b/providers/frontLogger.js
similarity index 87%
rename from providers/logger.js
rename to providers/frontLogger.js
index 730a3dfa..210e3ff8 100644
--- a/providers/logger.js
+++ b/providers/frontLogger.js
@@ -3,7 +3,7 @@ const { ipcRenderer } = require("electron");
function logToString(log) {
let string = (typeof log === "string") ? log : log.toString();
if (!string || string.includes("[object Object]")) {
- string = JSON.stringify(log);
+ string = JSON.stringify(log, null, "\t");
}
return string;
}
From c764d657d74fc5d85d0410ec1115d42e84bdc7df Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Wed, 14 Apr 2021 13:42:39 +0300
Subject: [PATCH 32/52] cleanup unresponsiveDialog
---
index.js | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/index.js b/index.js
index addd98ed..13eaa2db 100644
--- a/index.js
+++ b/index.js
@@ -341,15 +341,11 @@ function showUnresponsiveDialog(win, details) {
case 1: //if relaunch - relaunch+exit
app.relaunch();
case 2:
- app.exit();
+ app.quit();
break;
case 0:
default:
return;
- //maybe set a timer and afterwards check responsivness and call function again if failed
}
});
}
-
-module.exports.aDialog = showUnresponsiveDialog;
-
From bb6ad14111608d3b085a50e1c4a0a6d77ce37252 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Thu, 15 Apr 2021 12:40:09 +0300
Subject: [PATCH 33/52] navbar background black fix visual bug
---
plugins/in-app-menu/style.css | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/plugins/in-app-menu/style.css b/plugins/in-app-menu/style.css
index 19dd59fb..c6339093 100644
--- a/plugins/in-app-menu/style.css
+++ b/plugins/in-app-menu/style.css
@@ -21,6 +21,16 @@ ytmusic-pivot-bar-item-renderer {
-webkit-app-region: unset !important;
}
+/* navbar background black */
+.center-content.ytmusic-nav-bar {
+ background: #030303;
+}
+
+/* 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;
From ff6a486daf145c5a56ec5f500f29fdbf1c38391b Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Thu, 15 Apr 2021 15:34:05 +0300
Subject: [PATCH 34/52] fix unresponsive dialog response
---
index.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/index.js b/index.js
index 13eaa2db..82ba695d 100644
--- a/index.js
+++ b/index.js
@@ -333,11 +333,11 @@ function showUnresponsiveDialog(win, details) {
type: "error",
title: "Window Unresponsive",
message: "The Application is Unresponsive",
- details: "We are sorry for the inconveniance! please choose what to do with the application:",
+ details: "We are sorry for the inconveniance! please choose what to do:",
buttons: ["Wait", "Relaunch", "Quit"],
cancelId: 0
- }).then( response => {
- switch (response) {
+ }).then( result => {
+ switch (result.response) {
case 1: //if relaunch - relaunch+exit
app.relaunch();
case 2:
@@ -345,7 +345,7 @@ function showUnresponsiveDialog(win, details) {
break;
case 0:
default:
- return;
+ break;
}
});
}
From 341a06aae70cf42b913ca73f5a0deb5b3afa3537 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sat, 17 Apr 2021 20:30:06 +0300
Subject: [PATCH 35/52] add prompt with number counter
---
menu.js | 2 +-
package.json | 1 -
providers/prompt/dark-prompt.css | 5 ++
providers/prompt/index.js | 16 ++++-
providers/prompt/page/prompt.css | 32 +++++++++
providers/prompt/page/prompt.js | 114 +++++++++++++++++++++++--------
providers/prompt/readme.md | 5 +-
yarn.lock | 12 ----
8 files changed, 140 insertions(+), 47 deletions(-)
diff --git a/menu.js b/menu.js
index 90487970..588dad7c 100644
--- a/menu.js
+++ b/menu.js
@@ -335,7 +335,7 @@ function setProxy(item, win) {
});
}
prompt(options, win)
- .then((input) => {
+ .then(input => {
if (input !== null && input !== example) {
config.set("options.proxy", input);
item.checked = input !== "";
diff --git a/package.json b/package.json
index 144ac53f..a856babf 100644
--- a/package.json
+++ b/package.json
@@ -70,7 +70,6 @@
"browser-id3-writer": "^4.4.0",
"custom-electron-titlebar": "^3.2.6",
"discord-rpc": "^3.2.0",
- "doc-ready": "^1.0.4",
"downloads-folder": "^3.0.1",
"electron-debug": "^3.2.0",
"electron-is": "^3.0.0",
diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css
index 49e0f88e..74fea61e 100644
--- a/providers/prompt/dark-prompt.css
+++ b/providers/prompt/dark-prompt.css
@@ -45,3 +45,8 @@ body {
background-color: rgb(0, 0, 0);
color: whitesmoke;
}
+
+.minus,
+.plus {
+ background:rgb(0, 0, 0);
+}
\ No newline at end of file
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index bbba8b78..1c14cfa2 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -6,7 +6,9 @@ const url = require("url");
const path = require("path");
const DEFAULT_WIDTH = 370;
+const DEFAULT_COUNTER_WIDTH = 300;
const DEFAULT_HEIGHT = 160;
+const DEFAULT_COUNTER_HEIGHT= 150;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
@@ -18,8 +20,6 @@ function electronPrompt(options, parentWindow) {
{
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
- minWidth: DEFAULT_WIDTH,
- minHeight: DEFAULT_HEIGHT,
resizable: false,
title: "Prompt",
label: "Please input a value:",
@@ -40,6 +40,11 @@ function electronPrompt(options, parentWindow) {
options || {}
);
+ options_.minWidth = options.minWidth || options.width ||
+ options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH;
+ options_.minHeight = options.minHeight || options.height ||
+ options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT;
+
if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
reject(new Error('"selectOptions" must be an object'));
return;
@@ -136,6 +141,13 @@ function electronPrompt(options, parentWindow) {
reject(new Error("prompt.html did-fail-load, log:\n", + log.toString()));
});
+ const promptUrl = url.format({
+ protocol: 'file',
+ slashes: true,
+ pathname: path.join(__dirname, 'page', 'prompt.html'),
+ hash: id
+ });
+
//Finally, load prompt
promptWindow.loadURL(promptUrl);
});
diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css
index c3530e57..10654b8d 100644
--- a/providers/prompt/page/prompt.css
+++ b/providers/prompt/page/prompt.css
@@ -78,3 +78,35 @@ select#data {
background-color: #ddd;
color: black;
}
+
+/* Counter mode css */
+
+span {
+ cursor: pointer;
+}
+.number {
+ margin: 100px;
+}
+.minus,
+.plus {
+ user-select: none;
+ width: 20px;
+ height: 20px;
+ background: #f2f2f2;
+ border-radius: 4px;
+ padding: 8px 5px 8px 5px;
+ border: 1px solid #ddd;
+ display: inline-block;
+ vertical-align: middle;
+ text-align: center;
+}
+.inputt {
+ height: 34px;
+ width: 100px;
+ text-align: center;
+ font-size: 26px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ display: inline-block;
+ vertical-align: middle;
+}
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index b7a54120..042ba546 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -1,13 +1,13 @@
const fs = require("fs");
const {ipcRenderer} = require("electron");
-const docReady = require("doc-ready");
let promptId = null;
let promptOptions = null;
+function $(selector) {return document.querySelector(selector)}
+
+document.addEventListener( 'DOMContentLoaded', promptRegister);
-docReady(promptRegister);
-//start here
function promptRegister() {
//get custom session id
promptId = document.location.hash.replace("#", "");
@@ -21,18 +21,18 @@ function promptRegister() {
//set label
if (promptOptions.useHtmlLabel) {
- document.querySelector("#label").innerHTML = promptOptions.label;
+ $("#label").innerHTML = promptOptions.label;
} else {
- document.querySelector("#label").textContent = promptOptions.label;
+ $("#label").textContent = promptOptions.label;
}
//set button label
if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
- document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
+ $("#ok").textContent = promptOptions.buttonLabels.ok;
}
if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
- document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
+ $("#cancel").textContent = promptOptions.buttonLabels.cancel;
}
//inject custom stylesheet from options
@@ -51,26 +51,40 @@ function promptRegister() {
}
//add button listeners
- document.querySelector("#form").addEventListener("submit", promptSubmit);
- document.querySelector("#cancel").addEventListener("click", promptCancel);
+ $("#form").addEventListener("submit", promptSubmit);
+ $("#cancel").addEventListener("click", promptCancel);
//create input/select
- const dataContainerElement = document.querySelector("#data-container");
+ const dataContainerElement = $("#data-container");
let dataElement;
- if (promptOptions.type === "input") {
- dataElement = promptCreateInput();
- } else if (promptOptions.type === "select") {
- dataElement = promptCreateSelect();
- } else {
- return promptError(`Unhandled input type '${promptOptions.type}'`);
- }
- dataContainerElement.append(dataElement);
+ switch (promptOptions.type) {
+ case "counter":
+ case "input":
+ dataElement = promptCreateInput();
+ break;
+ case "select":
+ dataElement = promptCreateSelect();
+ break;
+ default:
+ return promptError(`Unhandled input type '${promptOptions.type}'`);
+ }
+ if (promptOptions.type === "counter") {
+ dataElement.classList.add("input");
+ dataElement.style.width = "unset";
+ dataElement.style["text-align"] = "center";
+ //dataElement.style["min-height"] = "1.5em";
+ dataContainerElement.append(createMinus(dataElement));
+ dataContainerElement.append(dataElement);
+ dataContainerElement.append(createPlus(dataElement));
+ } else {
+ dataContainerElement.append(dataElement);
+ }
dataElement.setAttribute("id", "data");
dataElement.focus();
- if (promptOptions.type === "input") {
+ if (promptOptions.type === "input" || promptOptions.type === "counter") {
dataElement.select();
}
@@ -87,7 +101,8 @@ function promptRegister() {
window.addEventListener("error", error => {
if (promptId) {
- promptError("An error has occured on the prompt window: \n" + error);
+ promptError("An error has occured on the prompt window: \n" + JSON.stringify(error, ["message", "arguments", "type", "name"])
+ );
}
});
@@ -107,15 +122,23 @@ function promptCancel() {
//transfer input data to back
function promptSubmit() {
- const dataElement = document.querySelector("#data");
+ const dataElement = $("#data");
let data = null;
- if (promptOptions.type === "input") {
- data = dataElement.value;
- } else if (promptOptions.type === "select") {
- data = promptOptions.selectMultiple ?
- dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
- dataElement.value;
+ switch (promptOptions.type) {
+ case "input":
+ data = dataElement.value;
+ break;
+ case "counter":
+ data = validateCounterInput(dataElement.value);
+ break;
+ case "select":
+ data = promptOptions.selectMultiple ?
+ dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
+ dataElement.value;
+ break;
+ default: //will never happen
+ return promptError(`Unhandled input type '${promptOptions.type}'`);
}
ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
@@ -127,6 +150,9 @@ function promptCreateInput() {
dataElement.setAttribute("type", "text");
if (promptOptions.value) {
+ if (promptOptions.type === "counter") {
+ promptOptions.value = validateCounterInput(promptOptions.value);
+ }
dataElement.value = promptOptions.value;
} else {
dataElement.value = "";
@@ -150,11 +176,11 @@ function promptCreateInput() {
}
});
- //Confrim on 'Enter'
+ //Confirm on 'Enter'
dataElement.addEventListener("keypress", event => {
if (event.key === "Enter") {
event.preventDefault();
- document.querySelector("#ok").click();
+ $("#ok").click();
}
});
@@ -184,5 +210,35 @@ function promptCreateSelect() {
return dataElement;
}
+function createMinus(dataElement) {
+ const minus = document.createElement("span");
+ minus.textContent = "-";
+ minus.classList.add("minus");
+ minus.onmousedown = () => {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
+ };
+ return minus;
+}
+function createPlus(dataElement) {
+ const plus = document.createElement("span");
+ plus.textContent = "+";
+ plus.classList.add("plus");
+ plus.onmousedown = () => {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
+ };
+ return plus;
+}
+//validate counter
+function validateCounterInput(input) {
+ const min = promptOptions.counterOptions?.minimum,
+ max = promptOptions.counterOptions?.maximum;
+ if (min !== undefined && input < min) {
+ return min;
+ }
+ if (max !== undefined && input > max) {
+ return max;
+ }
+ return input;
+}
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
index 6683aced..eff1f907 100644
--- a/providers/prompt/readme.md
+++ b/providers/prompt/readme.md
@@ -43,8 +43,9 @@ prompt({
| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. |
| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. |
| value | (optional, string) The default value for the input field. Defaults to null. |
-| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. |
-| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input' |
+| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. |
+| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input'
+| counterOptions | (optional, object) minimum and maximum of counter in format: `{minimum: %int%, maximum: %int%} ` |
| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
| width | (optional, integer) The width of the prompt window. Defaults to 370. |
diff --git a/yarn.lock b/yarn.lock
index f9909214..c969527e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2908,13 +2908,6 @@ dmg-builder@22.9.1:
js-yaml "^3.14.0"
sanitize-filename "^1.6.3"
-doc-ready@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/doc-ready/-/doc-ready-1.0.4.tgz#37f5391969cff994303fdfef2e5d50357f8164d3"
- integrity sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM=
- dependencies:
- eventie "^1"
-
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@@ -3612,11 +3605,6 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
-eventie@^1:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/eventie/-/eventie-1.0.6.tgz#d4ffc8b0c2b5e493c2aa1b22cbe918d3aee74437"
- integrity sha1-1P/IsMK15JPCqhsiy+kY067nRDc=
-
events@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379"
From 3f50ab7cfc8c0efcacd35848baf2cf499f8f4706 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sat, 17 Apr 2021 20:43:48 +0300
Subject: [PATCH 36/52] lint
---
providers/prompt/dark-prompt.css | 4 ++--
providers/prompt/page/prompt.css | 14 --------------
providers/prompt/page/prompt.js | 11 +++++------
3 files changed, 7 insertions(+), 22 deletions(-)
diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css
index 74fea61e..8bf39791 100644
--- a/providers/prompt/dark-prompt.css
+++ b/providers/prompt/dark-prompt.css
@@ -48,5 +48,5 @@ body {
.minus,
.plus {
- background:rgb(0, 0, 0);
-}
\ No newline at end of file
+ background: rgb(0, 0, 0);
+}
diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css
index 10654b8d..3224cf6a 100644
--- a/providers/prompt/page/prompt.css
+++ b/providers/prompt/page/prompt.css
@@ -80,13 +80,9 @@ select#data {
}
/* Counter mode css */
-
span {
cursor: pointer;
}
-.number {
- margin: 100px;
-}
.minus,
.plus {
user-select: none;
@@ -100,13 +96,3 @@ span {
vertical-align: middle;
text-align: center;
}
-.inputt {
- height: 34px;
- width: 100px;
- text-align: center;
- font-size: 26px;
- border: 1px solid #ddd;
- border-radius: 4px;
- display: inline-block;
- vertical-align: middle;
-}
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 042ba546..d3abfeab 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -1,12 +1,12 @@
const fs = require("fs");
-const {ipcRenderer} = require("electron");
+const { ipcRenderer } = require("electron");
let promptId = null;
let promptOptions = null;
-function $(selector) {return document.querySelector(selector)}
+function $(selector) { return document.querySelector(selector) }
-document.addEventListener( 'DOMContentLoaded', promptRegister);
+document.addEventListener('DOMContentLoaded', promptRegister);
function promptRegister() {
//get custom session id
@@ -71,7 +71,6 @@ function promptRegister() {
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
if (promptOptions.type === "counter") {
- dataElement.classList.add("input");
dataElement.style.width = "unset";
dataElement.style["text-align"] = "center";
//dataElement.style["min-height"] = "1.5em";
@@ -215,7 +214,7 @@ function createMinus(dataElement) {
minus.textContent = "-";
minus.classList.add("minus");
minus.onmousedown = () => {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
};
return minus;
}
@@ -233,7 +232,7 @@ function createPlus(dataElement) {
//validate counter
function validateCounterInput(input) {
const min = promptOptions.counterOptions?.minimum,
- max = promptOptions.counterOptions?.maximum;
+ max = promptOptions.counterOptions?.maximum;
if (min !== undefined && input < min) {
return min;
}
From 97a9e632317c674bae580f818d474fd21487698d Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sat, 17 Apr 2021 21:17:07 +0300
Subject: [PATCH 37/52] xo --fix
---
preload.js | 2 +-
providers/{frontLogger.js => front-logger.js} | 0
providers/prompt/index.js | 16 +++---
providers/prompt/page/prompt.js | 51 +++++++++++--------
4 files changed, 38 insertions(+), 31 deletions(-)
rename providers/{frontLogger.js => front-logger.js} (100%)
diff --git a/preload.js b/preload.js
index 5fcb2e07..74860cec 100644
--- a/preload.js
+++ b/preload.js
@@ -34,7 +34,7 @@ document.addEventListener("DOMContentLoaded", () => {
fileExists(songInfoProviderPath, require(songInfoProviderPath));
// inject front logger
- const loggerPath = path.join(__dirname, "providers", "frontLogger.js")
+ const loggerPath = path.join(__dirname, "providers", "front-logger.js")
fileExists(loggerPath, require(loggerPath));
// Add action for reloading
diff --git a/providers/frontLogger.js b/providers/front-logger.js
similarity index 100%
rename from providers/frontLogger.js
rename to providers/front-logger.js
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 1c14cfa2..1e29766f 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -8,7 +8,7 @@ const path = require("path");
const DEFAULT_WIDTH = 370;
const DEFAULT_COUNTER_WIDTH = 300;
const DEFAULT_HEIGHT = 160;
-const DEFAULT_COUNTER_HEIGHT= 150;
+const DEFAULT_COUNTER_HEIGHT = 150;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
@@ -40,9 +40,9 @@ function electronPrompt(options, parentWindow) {
options || {}
);
- options_.minWidth = options.minWidth || options.width ||
+ options_.minWidth = options.minWidth || options.width ||
options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH;
- options_.minHeight = options.minHeight || options.height ||
+ options_.minHeight = options.minHeight || options.height ||
options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT;
if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
@@ -130,21 +130,21 @@ function electronPrompt(options, parentWindow) {
event,
errorCode,
errorDescription,
- validatedURL,
+ validatedURL
) => {
const log = {
error: "did-fail-load",
errorCode,
errorDescription,
- validatedURL,
+ validatedURL
};
- reject(new Error("prompt.html did-fail-load, log:\n", + log.toString()));
+ reject(new Error("prompt.html did-fail-load, log:\n" + log.toString()));
});
const promptUrl = url.format({
- protocol: 'file',
+ protocol: "file",
slashes: true,
- pathname: path.join(__dirname, 'page', 'prompt.html'),
+ pathname: path.join(__dirname, "page", "prompt.html"),
hash: id
});
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index d3abfeab..ac79f106 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -4,9 +4,11 @@ const { ipcRenderer } = require("electron");
let promptId = null;
let promptOptions = null;
-function $(selector) { return document.querySelector(selector) }
+function $(selector) {
+ return document.querySelector(selector);
+}
-document.addEventListener('DOMContentLoaded', promptRegister);
+document.addEventListener("DOMContentLoaded", promptRegister);
function promptRegister() {
//get custom session id
@@ -54,7 +56,6 @@ function promptRegister() {
$("#form").addEventListener("submit", promptSubmit);
$("#cancel").addEventListener("click", promptCancel);
-
//create input/select
const dataContainerElement = $("#data-container");
let dataElement;
@@ -70,19 +71,20 @@ function promptRegister() {
default:
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
+
if (promptOptions.type === "counter") {
dataElement.style.width = "unset";
dataElement.style["text-align"] = "center";
- //dataElement.style["min-height"] = "1.5em";
- dataContainerElement.append(createMinus(dataElement));
+ dataContainerElement.append(createMinusButton(dataElement));
dataContainerElement.append(dataElement);
- dataContainerElement.append(createPlus(dataElement));
+ dataContainerElement.append(createPlusButton(dataElement));
} else {
dataContainerElement.append(dataElement);
}
- dataElement.setAttribute("id", "data");
+ dataElement.setAttribute("id", "data");
dataElement.focus();
+
if (promptOptions.type === "input" || promptOptions.type === "counter") {
dataElement.select();
}
@@ -100,7 +102,8 @@ function promptRegister() {
window.addEventListener("error", error => {
if (promptId) {
- promptError("An error has occured on the prompt window: \n" + JSON.stringify(error, ["message", "arguments", "type", "name"])
+ promptError("An error has occured on the prompt window: \n" +
+ JSON.stringify(error, ["message", "arguments", "type", "name"])
);
}
});
@@ -209,35 +212,39 @@ function promptCreateSelect() {
return dataElement;
}
-function createMinus(dataElement) {
- const minus = document.createElement("span");
- minus.textContent = "-";
- minus.classList.add("minus");
- minus.onmousedown = () => {
+function createMinusButton(dataElement) {
+ const minusBtn = document.createElement("span");
+ minusBtn.textContent = "-";
+ minusBtn.classList.add("minus");
+ minusBtn.onmousedown = () => {
dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
};
- return minus;
+ return minusBtn;
}
-function createPlus(dataElement) {
- const plus = document.createElement("span");
- plus.textContent = "+";
- plus.classList.add("plus");
- plus.onmousedown = () => {
+function createPlusButton(dataElement) {
+ const plusBtn = document.createElement("span");
+ plusBtn.textContent = "+";
+ plusBtn.classList.add("plus");
+ plusBtn.onmousedown = () => {
dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
};
- return plus;
+
+ return plusBtn;
}
//validate counter
function validateCounterInput(input) {
- const min = promptOptions.counterOptions?.minimum,
- max = promptOptions.counterOptions?.maximum;
+ const min = promptOptions.counterOptions?.minimum;
+ const max = promptOptions.counterOptions?.maximum;
+
if (min !== undefined && input < min) {
return min;
}
+
if (max !== undefined && input > max) {
return max;
}
+
return input;
}
From b7b1316e7095565eb0c6370f46dc1fee972df61e Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sat, 17 Apr 2021 22:55:25 +0300
Subject: [PATCH 38/52] add rapidFire option to counter prompt
---
providers/prompt/index.js | 16 +++++---
providers/prompt/page/prompt.js | 69 +++++++++++++++++++++++++++------
providers/prompt/readme.md | 2 +-
3 files changed, 69 insertions(+), 18 deletions(-)
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 1e29766f..009c8c7a 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -18,8 +18,8 @@ function electronPrompt(options, parentWindow) {
//custom options override default
const options_ = Object.assign(
{
- width: DEFAULT_WIDTH,
- height: DEFAULT_HEIGHT,
+ width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH,
+ height:options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT: DEFAULT_HEIGHT,
resizable: false,
title: "Prompt",
label: "Please input a value:",
@@ -28,6 +28,7 @@ function electronPrompt(options, parentWindow) {
value: null,
type: "input",
selectOptions: null,
+ counterOptions: {minimum: null, maximum: null, multiFire: false},
icon: null,
useHtmlLabel: false,
customStylesheet: null,
@@ -40,10 +41,13 @@ function electronPrompt(options, parentWindow) {
options || {}
);
- options_.minWidth = options.minWidth || options.width ||
- options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH;
- options_.minHeight = options.minHeight || options.height ||
- options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT;
+ options_.minWidth = options?.minWidth || options?.width || options_.width;
+ options_.minHeight = options?.minHeight || options?.height || options_.height;
+
+ if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) {
+ reject(new Error('"counterOptions" must be an object if specified'));
+ return;
+ }
if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
reject(new Error('"selectOptions" must be an object'));
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index ac79f106..3cad04ac 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -4,7 +4,7 @@ const { ipcRenderer } = require("electron");
let promptId = null;
let promptOptions = null;
-function $(selector) {
+function $(selector) {
return document.querySelector(selector);
}
@@ -62,6 +62,8 @@ function promptRegister() {
switch (promptOptions.type) {
case "counter":
+ dataElement = promptCreateCounter();
+ break;
case "input":
dataElement = promptCreateInput();
break;
@@ -73,8 +75,6 @@ function promptRegister() {
}
if (promptOptions.type === "counter") {
- dataElement.style.width = "unset";
- dataElement.style["text-align"] = "center";
dataContainerElement.append(createMinusButton(dataElement));
dataContainerElement.append(dataElement);
dataContainerElement.append(createPlusButton(dataElement));
@@ -212,27 +212,74 @@ function promptCreateSelect() {
return dataElement;
}
+let pressed = false;
+function multiFire(timer, scaleSpeed, callback, ...args) {
+ if (!pressed) {
+ return;
+ }
+ if (timer > scaleSpeed) {
+ timer -= scaleSpeed;
+ }
+ callback(...args);
+ setTimeout(multiFire, timer, timer, scaleSpeed, callback, ...args)
+}
+
function createMinusButton(dataElement) {
+ function doMinus() {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
+ }
const minusBtn = document.createElement("span");
minusBtn.textContent = "-";
minusBtn.classList.add("minus");
- minusBtn.onmousedown = () => {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
- };
+ if (promptOptions.counterOptions?.multiFire) {
+ minusBtn.onmousedown = () => {
+ pressed = true;
+ multiFire(500, 100, doMinus);
+ };
+
+ } else {
+ minusBtn.onmousedown = () => {
+ doMinus();
+ };
+ }
return minusBtn;
}
function createPlusButton(dataElement) {
+ function doPlus() {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
+ }
const plusBtn = document.createElement("span");
plusBtn.textContent = "+";
plusBtn.classList.add("plus");
- plusBtn.onmousedown = () => {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
- };
-
+ if (promptOptions.counterOptions?.multiFire) {
+ plusBtn.onmousedown = () => {
+ pressed = true;
+ multiFire(500, 100, doPlus);
+ };
+ } else {
+ plusBtn.onmousedown = () => {
+ doPlus();
+ };
+ }
return plusBtn;
}
+function promptCreateCounter() {
+ if (promptOptions.counterOptions?.multiFire) {
+ document.onmouseup = () => {
+ pressed = false;
+ };
+ }
+
+ const dataElement = promptCreateInput();
+
+ dataElement.style.width = "unset";
+ dataElement.style["text-align"] = "center";
+
+ return dataElement;
+}
+
//validate counter
function validateCounterInput(input) {
const min = promptOptions.counterOptions?.minimum;
@@ -245,6 +292,6 @@ function validateCounterInput(input) {
if (max !== undefined && input > max) {
return max;
}
-
+
return input;
}
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
index eff1f907..ec272375 100644
--- a/providers/prompt/readme.md
+++ b/providers/prompt/readme.md
@@ -45,7 +45,7 @@ prompt({
| value | (optional, string) The default value for the input field. Defaults to null. |
| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. |
| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input'
-| counterOptions | (optional, object) minimum and maximum of counter in format: `{minimum: %int%, maximum: %int%} ` |
+| counterOptions | (optional, object) minimum and maximum of counter, and if continuous input is enabled. format: `{minimum: %int%, maximum: %int%, multiFire: %boolean%`. min+max values defaults to null and multiFire defaults to false. |
| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
| width | (optional, integer) The width of the prompt window. Defaults to 370. |
From 00468c7d0ec1db09786ae3385fc3a0413226e40a Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sun, 18 Apr 2021 00:44:22 +0300
Subject: [PATCH 39/52] use timeout ID to stop callback
---
providers/prompt/page/prompt.js | 73 ++++++++++++++++++++++++---------
1 file changed, 53 insertions(+), 20 deletions(-)
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 3cad04ac..b4759e2d 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -212,29 +212,60 @@ function promptCreateSelect() {
return dataElement;
}
-let pressed = false;
-function multiFire(timer, scaleSpeed, callback, ...args) {
- if (!pressed) {
- return;
+let nextTimeoutID = null;
+
+/* Function execute callback in 3 accelerated intervals based on timer.
+ * Terminated from document.onmouseup() that is registered from promptCreateCounter()
+ * @param {function} callback: function to execute
+ * @param {object} timer: {
+ * * time: First delay in miliseconds.
+ * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
+ * * scaleSpeed: Speed change per tick on first acceleration
+ * }
+ * @param {int} stepArgs: argument for callback representing Initial steps per click, default to 1
+ * steps starts to increase when speed is too fast to notice
+ * @param {int} counter: used internally to decrease timer.limit
+ */
+function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) {
+ callback(stepsArg);
+
+ const nextTimeout = timer.time
+
+ if (counter > 20) {
+ counter = 0 - stepsArg;
+ if (timer.limit > 1) {
+ timer.limit = timer.limit / 2;
+ } else {
+ stepsArg *= 2;
+ }
}
- if (timer > scaleSpeed) {
- timer -= scaleSpeed;
+ if (timer.time != timer.limit) {
+ timer.time = timer.time > timer.limit ?
+ timer.time - timer.scaleSpeed :
+ timer.limit;
}
- callback(...args);
- setTimeout(multiFire, timer, timer, scaleSpeed, callback, ...args)
+
+ nextTimeoutID = setTimeout(
+ multiFire, //callback
+ nextTimeout, //timer
+ //multiFire args:
+ callback,
+ timer,
+ stepsArg,
+ counter + 1
+ )
}
function createMinusButton(dataElement) {
- function doMinus() {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
+ function doMinus(steps) {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps);
}
const minusBtn = document.createElement("span");
minusBtn.textContent = "-";
minusBtn.classList.add("minus");
if (promptOptions.counterOptions?.multiFire) {
minusBtn.onmousedown = () => {
- pressed = true;
- multiFire(500, 100, doMinus);
+ multiFire(doMinus);
};
} else {
@@ -246,16 +277,15 @@ function createMinusButton(dataElement) {
}
function createPlusButton(dataElement) {
- function doPlus() {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
+ function doPlus(steps) {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps);
}
const plusBtn = document.createElement("span");
plusBtn.textContent = "+";
plusBtn.classList.add("plus");
if (promptOptions.counterOptions?.multiFire) {
plusBtn.onmousedown = () => {
- pressed = true;
- multiFire(500, 100, doPlus);
+ multiFire(doPlus);
};
} else {
plusBtn.onmousedown = () => {
@@ -268,7 +298,10 @@ function createPlusButton(dataElement) {
function promptCreateCounter() {
if (promptOptions.counterOptions?.multiFire) {
document.onmouseup = () => {
- pressed = false;
+ if (!!nextTimeoutID) {
+ clearTimeout(nextTimeoutID)
+ nextTimeoutID = null;
+ }
};
}
@@ -284,12 +317,12 @@ function promptCreateCounter() {
function validateCounterInput(input) {
const min = promptOptions.counterOptions?.minimum;
const max = promptOptions.counterOptions?.maximum;
-
- if (min !== undefined && input < min) {
+ //note that !min/max would proc if min/max are 0
+ if (min !== null && min !== undefined && input < min) {
return min;
}
- if (max !== undefined && input > max) {
+ if (max !== null && max !== undefined && input > max) {
return max;
}
From 72716afcd3fcba96714c360257d95cb77af125a8 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sun, 18 Apr 2021 01:44:18 +0300
Subject: [PATCH 40/52] lint
---
menu.js | 6 +++---
providers/prompt/index.js | 8 ++++++--
providers/prompt/page/prompt.js | 18 ++++++++++++------
providers/prompt/readme.md | 6 +++---
4 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/menu.js b/menu.js
index 588dad7c..dddce721 100644
--- a/menu.js
+++ b/menu.js
@@ -149,7 +149,7 @@ const mainMenuTemplate = (win) => [
type: "checkbox",
checked: !!config.get("options.proxy"),
click: (item) => {
- setProxy(item, win);
+ setProxy(item, win);
}
},
{
@@ -322,10 +322,10 @@ function setProxy(item, win) {
},
type: 'input',
icon: iconPath,
- customStylesheet: path.join(__dirname, "providers", "prompt", "dark-prompt.css"),
+ customStylesheet: "dark",
};
//TODO: custom bar on prompt need testing on macOS
- if(!is.macOS()) {
+ if (!is.macOS()) {
Object.assign(options, {
frame: false,
customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"),
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 009c8c7a..95babc9c 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -19,7 +19,7 @@ function electronPrompt(options, parentWindow) {
const options_ = Object.assign(
{
width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH,
- height:options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT: DEFAULT_HEIGHT,
+ height: options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT,
resizable: false,
title: "Prompt",
label: "Please input a value:",
@@ -28,7 +28,7 @@ function electronPrompt(options, parentWindow) {
value: null,
type: "input",
selectOptions: null,
- counterOptions: {minimum: null, maximum: null, multiFire: false},
+ counterOptions: { minimum: null, maximum: null, multiFire: false },
icon: null,
useHtmlLabel: false,
customStylesheet: null,
@@ -44,6 +44,10 @@ function electronPrompt(options, parentWindow) {
options_.minWidth = options?.minWidth || options?.width || options_.width;
options_.minHeight = options?.minHeight || options?.height || options_.height;
+ if (options_.customStylesheet === "dark") {
+ options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css");
+ }
+
if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) {
reject(new Error('"counterOptions" must be an object if specified'));
return;
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index b4759e2d..7f609b52 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -229,17 +229,18 @@ let nextTimeoutID = null;
function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) {
callback(stepsArg);
- const nextTimeout = timer.time
+ const nextTimeout = timer.time;
if (counter > 20) {
counter = 0 - stepsArg;
if (timer.limit > 1) {
- timer.limit = timer.limit / 2;
+ timer.limit /= 2;
} else {
stepsArg *= 2;
}
}
- if (timer.time != timer.limit) {
+
+ if (timer.time !== timer.limit) {
timer.time = timer.time > timer.limit ?
timer.time - timer.scaleSpeed :
timer.limit;
@@ -253,26 +254,28 @@ function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 },
timer,
stepsArg,
counter + 1
- )
+ );
}
function createMinusButton(dataElement) {
function doMinus(steps) {
dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps);
}
+
const minusBtn = document.createElement("span");
minusBtn.textContent = "-";
minusBtn.classList.add("minus");
+
if (promptOptions.counterOptions?.multiFire) {
minusBtn.onmousedown = () => {
multiFire(doMinus);
};
-
} else {
minusBtn.onmousedown = () => {
doMinus();
};
}
+
return minusBtn;
}
@@ -280,9 +283,11 @@ function createPlusButton(dataElement) {
function doPlus(steps) {
dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps);
}
+
const plusBtn = document.createElement("span");
plusBtn.textContent = "+";
plusBtn.classList.add("plus");
+
if (promptOptions.counterOptions?.multiFire) {
plusBtn.onmousedown = () => {
multiFire(doPlus);
@@ -292,13 +297,14 @@ function createPlusButton(dataElement) {
doPlus();
};
}
+
return plusBtn;
}
function promptCreateCounter() {
if (promptOptions.counterOptions?.multiFire) {
document.onmouseup = () => {
- if (!!nextTimeoutID) {
+ if (nextTimeoutID) {
clearTimeout(nextTimeoutID)
nextTimeoutID = null;
}
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
index ec272375..a3775b8d 100644
--- a/providers/prompt/readme.md
+++ b/providers/prompt/readme.md
@@ -1,6 +1,6 @@
# Prompt Documentation
-
+Simplest Prompt:
## Usage
```js
@@ -49,13 +49,13 @@ prompt({
| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
| width | (optional, integer) The width of the prompt window. Defaults to 370. |
-| minWidth | (optional, integer) The minimum allowed width for the prompt window. Same default value as width. |
+| minWidth | (optional, integer) The minimum allowed width for the prompt window. Default to width if specified or default_width(370). | |
| height | (optional, integer) The height of the prompt window. Defaults to 130. |
| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. |
| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. |
| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false |
| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. |
-| customStylesheet | (optional, string) The local path of a CSS file to stylize the prompt window. Defaults to null. |
+| customStylesheet | (optional, string) The local path of a CSS file to customize the style of the prompt window, you can use just "dark" to use the premade dark skin. Defaults to null. |
| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. |
| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. |
| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. |
From a1940461688bb3ab42450e426a26fd8ff4f72edf Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Fri, 23 Apr 2021 04:06:54 +0300
Subject: [PATCH 41/52] `win.once()` instead of `win.on`
---
plugins/in-app-menu/back.js | 2 +-
plugins/taskbar-mediacontrol/back.js | 2 +-
plugins/touchbar/back.js | 2 +-
plugins/utils.js | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/plugins/in-app-menu/back.js b/plugins/in-app-menu/back.js
index 8365ac8b..82b0af4f 100644
--- a/plugins/in-app-menu/back.js
+++ b/plugins/in-app-menu/back.js
@@ -41,7 +41,7 @@ module.exports = (winImport) => {
});
//set menu visibility on load
- win.webContents.on("did-finish-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"));
});
diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js
index b4d7dd3c..a8133539 100644
--- a/plugins/taskbar-mediacontrol/back.js
+++ b/plugins/taskbar-mediacontrol/back.js
@@ -24,7 +24,7 @@ module.exports = win => {
const {playPause, next, previous} = getSongControls(win);
// If the page is ready, register the callback
- win.on('ready-to-show', () => {
+ win.once('ready-to-show', () => {
registerCallback(songInfo => {
// Wait for song to start before setting thumbar
if (songInfo.title === '') {
diff --git a/plugins/touchbar/back.js b/plugins/touchbar/back.js
index 87240ed0..0fca17a7 100644
--- a/plugins/touchbar/back.js
+++ b/plugins/touchbar/back.js
@@ -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
diff --git a/plugins/utils.js b/plugins/utils.js
index b265692f..ed8c7c0a 100644
--- a/plugins/utils.js
+++ b/plugins/utils.js
@@ -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();
From eae4cca1484d610e18c71ea6d191b433bffc6dbe Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Fri, 23 Apr 2021 04:25:48 +0300
Subject: [PATCH 42/52] Update readme.md
---
providers/prompt/readme.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
index a3775b8d..613b4676 100644
--- a/providers/prompt/readme.md
+++ b/providers/prompt/readme.md
@@ -1,6 +1,6 @@
-# Prompt Documentation
+# Prompt Component Documentation
-Simplest Prompt:
+Simplest Prompt with no stylesheet:
## Usage
```js
From 5dc1179d54d6d0e7431c073e95309370cf8b268c Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Tue, 27 Apr 2021 23:48:06 +0300
Subject: [PATCH 43/52] implement keybind prompt
---
providers/prompt/dark-prompt.css | 28 ++-
providers/prompt/index.js | 34 ++--
providers/prompt/page/counter.js | 140 ++++++++++++++
providers/prompt/page/keybind.js | 305 +++++++++++++++++++++++++++++++
providers/prompt/page/prompt.css | 24 ++-
providers/prompt/page/prompt.js | 120 ++++++------
6 files changed, 578 insertions(+), 73 deletions(-)
create mode 100644 providers/prompt/page/counter.js
create mode 100644 providers/prompt/page/keybind.js
diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css
index 8bf39791..768b9e52 100644
--- a/providers/prompt/dark-prompt.css
+++ b/providers/prompt/dark-prompt.css
@@ -18,7 +18,8 @@ body {
overflow: hidden;
}
-#data {
+#data,
+.keybindData {
background: unset;
color: whitesmoke;
border: 1px solid rgb(54, 54, 54);
@@ -41,12 +42,35 @@ body {
}
#ok,
-#cancel {
+#cancel,
+.clearButton {
background-color: rgb(0, 0, 0);
color: whitesmoke;
}
+/* For Counter Prompt */
.minus,
.plus {
background: rgb(0, 0, 0);
}
+
+/* For Select Prompt */
+option {
+ background-color: #07070C;
+}
+
+/* For Keybind Prompt */
+.clearButton:focus {
+ outline: none;
+}
+.clearButton:hover {
+ background-color: rgb(5, 5, 5);
+}
+.keybindData:hover {
+ border: 1px solid rgb(56, 0, 0);
+}
+
+.keybindData:focus {
+ outline: 3px solid #1E0919;
+ border: 1px solid rgb(56, 0, 0);
+}
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
index 95babc9c..a5c2230c 100644
--- a/providers/prompt/index.js
+++ b/providers/prompt/index.js
@@ -6,9 +6,10 @@ const url = require("url");
const path = require("path");
const DEFAULT_WIDTH = 370;
+const DEFAULT_KEYBIND_WIDTH = 420;
const DEFAULT_COUNTER_WIDTH = 300;
-const DEFAULT_HEIGHT = 160;
-const DEFAULT_COUNTER_HEIGHT = 150;
+const DEFAULT_HEIGHT = 150;
+const DEFAULT_KEYBIND_HEIGHT = options => (options.length * 40) + 100;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
@@ -18,8 +19,8 @@ function electronPrompt(options, parentWindow) {
//custom options override default
const options_ = Object.assign(
{
- width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH,
- height: options?.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT,
+ width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : options?.type === "keybind" ? DEFAULT_KEYBIND_WIDTH : DEFAULT_WIDTH,
+ height: options?.type === "keybind" && options?.keybindOptions ? DEFAULT_KEYBIND_HEIGHT(options.keybindOptions) : DEFAULT_HEIGHT,
resizable: false,
title: "Prompt",
label: "Please input a value:",
@@ -28,6 +29,7 @@ function electronPrompt(options, parentWindow) {
value: null,
type: "input",
selectOptions: null,
+ keybindOptions: null,
counterOptions: { minimum: null, maximum: null, multiFire: false },
icon: null,
useHtmlLabel: false,
@@ -41,22 +43,21 @@ function electronPrompt(options, parentWindow) {
options || {}
);
- options_.minWidth = options?.minWidth || options?.width || options_.width;
- options_.minHeight = options?.minHeight || options?.height || options_.height;
+
if (options_.customStylesheet === "dark") {
options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css");
}
- if (options_.type === "counter" && (options_.counterOptions !== null && typeof options_.selectOptions !== "object")) {
- reject(new Error('"counterOptions" must be an object if specified'));
- return;
+ for (let type of ["counter", "select", "keybind"]) {
+ if (options_.type === type && (!options_[`${type}Options`] || typeof options_[`${type}Options`] !== "object")) {
+ reject(new Error(`"${type}Options" must be an object if type = ${type}`));
+ return;
+ }
}
- if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
- reject(new Error('"selectOptions" must be an object'));
- return;
- }
+ options_.minWidth = options?.minWidth || options?.width || options_.width;
+ options_.minHeight = options?.minHeight || options?.height || options_.height;
let promptWindow = new BrowserWindow({
frame: options_.frame,
@@ -104,6 +105,11 @@ function electronPrompt(options, parentWindow) {
//get input from front
const postDataListener = (event, value) => {
+ if (options_.type === "keybind" && value) {
+ for (let i=0; i < value.length ;i++) {
+ value[i] = JSON.parse(value[i])
+ }
+ }
resolve(value);
event.returnValue = null;
cleanup();
@@ -135,7 +141,7 @@ function electronPrompt(options, parentWindow) {
//should never happen
promptWindow.webContents.on("did-fail-load", (
- event,
+ _event,
errorCode,
errorDescription,
validatedURL
diff --git a/providers/prompt/page/counter.js b/providers/prompt/page/counter.js
new file mode 100644
index 00000000..6f773d97
--- /dev/null
+++ b/providers/prompt/page/counter.js
@@ -0,0 +1,140 @@
+const { promptCreateInput } = require("./prompt");
+
+module.exports = { promptCreateCounter , validateCounterInput }
+
+let options;
+
+
+function promptCreateCounter(promptOptions, parentElement) {
+ options = promptOptions;
+ if (options.counterOptions?.multiFire) {
+ document.onmouseup = () => {
+ if (nextTimeoutID) {
+ clearTimeout(nextTimeoutID)
+ nextTimeoutID = null;
+ }
+ };
+ }
+
+ options.value = validateCounterInput(options.value);
+
+ const dataElement = promptCreateInput();
+ dataElement.onkeypress = function isNumberKey(e) {
+ if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete")
+ return false;
+ return true;
+ }
+
+ dataElement.style.width = "unset";
+ dataElement.style["text-align"] = "center";
+
+ parentElement.append(createMinusButton(dataElement));
+ parentElement.append(dataElement);
+ parentElement.append(createPlusButton(dataElement));
+
+ return dataElement;
+}
+
+let nextTimeoutID = null;
+
+/** Function execute callback in 3 accelerated intervals based on timer.
+ * Terminated from document.onmouseup() that is registered from promptCreateCounter()
+ * @param {function} callback function to execute
+ * @param {object} timer {
+ * * time: First delay in miliseconds
+ * * scaleSpeed: Speed change per tick on first acceleration
+ * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
+ * }
+ * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1
+ * steps starts to increase when speed is too fast to notice
+ * @param {int} counter used internally to decrease timer.limit
+ */
+function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) {
+ callback(stepsArg);
+
+ const nextTimeout = timer.time;
+
+ if (counter > 20) {
+ counter = 0 - stepsArg;
+ if (timer.limit > 1) {
+ timer.limit /= 2;
+ } else {
+ stepsArg *= 2;
+ }
+ }
+
+ if (timer.time !== timer.limit) {
+ timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit)
+ }
+
+ nextTimeoutID = setTimeout(
+ multiFire, //callback
+ nextTimeout, //timer
+ //multiFire args:
+ callback,
+ timer,
+ stepsArg,
+ counter + 1
+ );
+}
+
+function createMinusButton(dataElement) {
+ function doMinus(steps) {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps);
+ }
+
+ const minusBtn = document.createElement("span");
+ minusBtn.textContent = "-";
+ minusBtn.classList.add("minus");
+
+ if (options.counterOptions?.multiFire) {
+ minusBtn.onmousedown = () => {
+ multiFire(doMinus);
+ };
+ } else {
+ minusBtn.onmousedown = () => {
+ doMinus();
+ };
+ }
+
+ return minusBtn;
+}
+
+function createPlusButton(dataElement) {
+ function doPlus(steps) {
+ dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps);
+ }
+
+ const plusBtn = document.createElement("span");
+ plusBtn.textContent = "+";
+ plusBtn.classList.add("plus");
+
+ if (options.counterOptions?.multiFire) {
+ plusBtn.onmousedown = () => {
+ multiFire(doPlus);
+ };
+ } else {
+ plusBtn.onmousedown = () => {
+ doPlus();
+ };
+ }
+
+ return plusBtn;
+}
+
+//validate counter
+function validateCounterInput(input) {
+
+ const min = options.counterOptions?.minimum;
+ const max = options.counterOptions?.maximum;
+ //note that !min/max would proc if min/max are 0
+ if (min !== null && min !== undefined && input < min) {
+ return min;
+ }
+
+ if (max !== null && max !== undefined && input > max) {
+ return max;
+ }
+
+ return input;
+}
diff --git a/providers/prompt/page/keybind.js b/providers/prompt/page/keybind.js
new file mode 100644
index 00000000..2406f736
--- /dev/null
+++ b/providers/prompt/page/keybind.js
@@ -0,0 +1,305 @@
+/* HTML
+
+
+ Example
+
+
+ Clear
+
+
+
+*/
+/* CSS
+
+div.keybind {
+ display: grid;
+ grid-template-columns: max-content max-content max-content;
+ grid-gap: 5px;
+}
+
+div.keybind button {
+ width: auto;
+}
+
+div.keybind label {
+ text-align: right;
+}
+
+div.keybind label:after {
+ content: ":";
+}
+
+*/
+const { promptError } = require("./prompt")
+
+class KeybindGetter {
+ value = null;
+ modifiers = null;
+ key = "";
+ label = null;
+ txt = null;
+ clearButton = null;
+
+ constructor(options, parentElement) {
+ if (!options.label || !options.value) {
+ promptError("keybind option must contain label and value");
+ return;
+ }
+
+ this.value = options.value
+ this.modifiers = new Set();
+ this.key = "";
+
+ this.label = document.createElement("label");
+ this.label.classList.add("keybindLabel");
+
+ this.txt = document.createElement("input");
+ this.txt.setAttribute('readonly', true);
+ this.txt.classList.add("keybindData");
+
+ this.clearButton = document.createElement("button");
+ this.clearButton.classList.add("clearButton");
+ this.clearButton.textContent = "Clear";
+ this.clearButton.onclick = (e) => e.preventDefault();
+
+ parentElement.append(this.label, this.txt, this.clearButton);
+
+ this.setup(options);
+ if (options.default) {
+ this.setDefault(options.default)
+ }
+ }
+
+ focus() {
+ this.txt.focus();
+ }
+
+ output() {
+ const output = {value: this.value, accelerator: this.txt.value.replaceAll(" ", "")}
+ return JSON.stringify(output);
+ }
+
+ updateText() {
+ let result = "";
+ for (let modifier of this.modifiers) {
+ result += modifier + " + ";
+ }
+ this.txt.value = result + this.key;
+ }
+
+ setDefault(defaultValue) {
+ const accelerator = parseAccelerator(defaultValue).split("+");
+ for (let key of accelerator) {
+ if (isModifier(key))
+ this.modifiers.add(key);
+ else
+ this.key = key;
+ }
+ this.updateText();
+ }
+ clear() {
+ this.modifiers.clear();
+ this.key = "";
+ this.txt.value = "";
+ }
+
+ setup(options) {
+ this.txt.addEventListener("keydown", (event) => {
+ event.preventDefault();
+ if (event.repeat) {
+ return
+ }
+ let key = event.code || event.key;
+ if (key in virtualKeyCodes)
+ key = virtualKeyCodes[event.code];
+ else {
+ console.log('Error, key "' + event.code + '" was not found');
+ return;
+ }
+
+ if (isModifier(key)) {
+ if (this.modifiers.size < 3)
+ this.modifiers.add(key);
+ } else { // is key
+ this.key = key;
+ }
+ this.updateText();
+ });
+
+ this.clearButton.addEventListener("click", () => {
+ this.clear()
+ });
+ this.label.textContent = options.label + " ";
+ }
+}
+
+class keybindContainer {
+ elements = [];
+
+ constructor(options, parentElement) {
+ parentElement.classList.add("keybind");
+ this.elements = options.map(option => new KeybindGetter(option, parentElement));
+ document.querySelector("#buttons").style["padding-top"] = "20px";
+ }
+
+ focus() {
+ if (this.elements.length > 0)
+ this.elements[0].focus();
+ }
+
+ submit() {
+ return this.elements.map(element => element.output());
+ }
+}
+
+function parseAccelerator(a) {
+ let accelerator = a.toString();
+
+ if (process.platform !== 'darwin') {
+ accelerator = accelerator.replace(/(Cmd)|(Command)/gi, '');
+ } else {
+ accelerator = accelerator.replace(/(Ctrl)|(Control)/gi, '');
+ }
+
+ accelerator = accelerator.replace(/(Or)/gi, '');
+
+ return accelerator;
+}
+
+function isModifier(key) {
+ for (let modifier of ["Shift", "Control", "Ctrl", "Command", "Cmd", "Alt", "AltGr", "Super"]) {
+ if (key === modifier)
+ return true;
+ }
+ return false;
+}
+
+const virtualKeyCodes = {
+ ShiftLeft: "Shift",
+ ShiftRight: "Shift",
+ ControlLeft: "Ctrl",
+ ControlRight: "Ctrl",
+ AltLeft: "Alt",
+ AltRight: "Alt",
+ MetaLeft: "Super",
+ MetaRight: "Super",
+ NumLock: "NumLock",
+ NumpadDivide: "NumDiv",
+ NumpadMultiply: "NumMult",
+ NumpadSubtract: "NumSub",
+ NumpadAdd: "NumAdd",
+ NumpadDecimal: "NumDec ",
+ Numpad0: "Num0",
+ Numpad1: "Num1",
+ Numpad2: "Num2",
+ Numpad3: "Num3",
+ Numpad4: "Num4",
+ Numpad5: "Num5",
+ Numpad6: "Num6",
+ Numpad7: "Num7",
+ Numpad8: "Num8",
+ Numpad9: "Num9",
+ Digit0: "0",
+ Digit1: "1",
+ Digit2: "2",
+ Digit3: "3",
+ Digit4: "4",
+ Digit5: "5",
+ Digit6: "6",
+ Digit7: "7",
+ Digit8: "8",
+ Digit9: "9",
+ Minus: "-",
+ Equal: "=",
+ KeyQ: "Q",
+ KeyW: "W",
+ KeyE: "E",
+ KeyR: "R",
+ KeyT: "T",
+ KeyY: "Y",
+ KeyU: "U",
+ KeyI: "I",
+ KeyO: "O",
+ KeyP: "P",
+ KeyA: "A",
+ KeyS: "S",
+ KeyD: "D",
+ KeyF: "F",
+ KeyG: "G",
+ KeyH: "H",
+ KeyJ: "J",
+ KeyK: "K",
+ KeyL: "L",
+ KeyZ: "Z",
+ KeyX: "X",
+ KeyC: "C",
+ KeyV: "V",
+ KeyB: "B",
+ KeyN: "N",
+ KeyM: "M",
+ BracketLeft: "[",
+ BracketRight: "]",
+ Semicolon: ";",
+ Quote: "'",
+ Backquote: '"',
+ Backslash: "\\",
+ Comma: ",",
+ Period: "'.'",
+ Slash: "/",
+ plus: '+',
+ Space: "Space",
+ Tab: "Tab",
+ Backspace: "Backspace",
+ Delete: "Delete",
+ Insert: "Insert",
+ Return: "Return",
+ Enter: "Enter",
+ ArrowUp: "Up",
+ ArrowDown: "Down",
+ ArrowLeft: "Left",
+ ArrowRight: "Right",
+ Home: "Home",
+ End: "End",
+ PageUp: "PageUp",
+ PageDown: "PageDown",
+ Escape: "Escape",
+ AudioVolumeUp: "VolumeUp",
+ AudioVolumeDown: "VolumeDown",
+ AudioVolumeMute: "VolumeMute",
+ MediaTrackNext: "MediaNextTrack",
+ MediaTrackPrevious: "MediaPreviousTrack",
+ MediaStop: "MediaStop",
+ MediaPlayPause: "MediaPlayPause",
+ ScrollLock: "ScrollLock",
+ PrintScreen: "PrintScreen",
+ F1: "F1",
+ F2: "F2",
+ F3: "F3",
+ F4: "F4",
+ F5: "F5",
+ F6: "F6",
+ F7: "F7",
+ F8: "F8",
+ F9: "F9",
+ F10: "F10",
+ F11: "F11",
+ F12: "F12",
+ F13: "F13",
+ F14: "F14",
+ F15: "F15",
+ F16: "F16",
+ F17: "F17",
+ F18: "F18",
+ F19: "F19",
+ F20: "F20",
+ F21: "F21",
+ F22: "F22",
+ F23: "F23",
+ F24: "F24",
+};
+
+
+
+module.exports = function promptCreateKeybind(options, parentElement) {
+ return new keybindContainer(options, parentElement);
+}
diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css
index 3224cf6a..6e52379a 100644
--- a/providers/prompt/page/prompt.css
+++ b/providers/prompt/page/prompt.css
@@ -79,7 +79,7 @@ select#data {
color: black;
}
-/* Counter mode css */
+/* Counter mode */
span {
cursor: pointer;
}
@@ -96,3 +96,25 @@ span {
vertical-align: middle;
text-align: center;
}
+
+/** Keybind mode */
+div.keybind {
+ display: grid;
+ grid-template-columns: max-content max-content max-content;
+ row-gap: 20px;
+ column-gap: 10px;
+ margin: auto 0;
+ justify-content: center;
+ }
+
+ div.keybind button {
+ width: auto;
+ }
+
+ div.keybind label {
+ text-align: right;
+ }
+
+ div.keybind label:after {
+ content: ":";
+ }
\ No newline at end of file
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
index 7f609b52..e09816d3 100644
--- a/providers/prompt/page/prompt.js
+++ b/providers/prompt/page/prompt.js
@@ -1,16 +1,15 @@
const fs = require("fs");
const { ipcRenderer } = require("electron");
-
let promptId = null;
let promptOptions = null;
+let dataElement = null;
-function $(selector) {
- return document.querySelector(selector);
-}
+function $(selector) { return document.querySelector(selector); }
document.addEventListener("DOMContentLoaded", promptRegister);
function promptRegister() {
+
//get custom session id
promptId = document.location.hash.replace("#", "");
@@ -56,13 +55,12 @@ function promptRegister() {
$("#form").addEventListener("submit", promptSubmit);
$("#cancel").addEventListener("click", promptCancel);
- //create input/select
+ //create input/select/counter/keybind
const dataContainerElement = $("#data-container");
- let dataElement;
switch (promptOptions.type) {
case "counter":
- dataElement = promptCreateCounter();
+ dataElement = promptCreateCounter(dataContainerElement);
break;
case "input":
dataElement = promptCreateInput();
@@ -70,22 +68,24 @@ function promptRegister() {
case "select":
dataElement = promptCreateSelect();
break;
+ case "keybind":
+ dataElement = require("./keybind")(promptOptions.keybindOptions, dataContainerElement);
+ break;
default:
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
- if (promptOptions.type === "counter") {
- dataContainerElement.append(createMinusButton(dataElement));
- dataContainerElement.append(dataElement);
- dataContainerElement.append(createPlusButton(dataElement));
- } else {
- dataContainerElement.append(dataElement);
+ if (promptOptions.type != "keybind") {
+ dataElement.setAttribute("id", "data");
+
+ if (promptOptions.type !== "counter") {
+ dataContainerElement.append(dataElement);
+ }
}
- dataElement.setAttribute("id", "data");
dataElement.focus();
- if (promptOptions.type === "input" || promptOptions.type === "counter") {
+ if (promptOptions.type !== "select" && promptOptions.type !== "keybind") {
dataElement.select();
}
@@ -100,10 +100,10 @@ function promptRegister() {
}
}
-window.addEventListener("error", error => {
+window.addEventListener("error", event => {
if (promptId) {
promptError("An error has occured on the prompt window: \n" +
- JSON.stringify(error, ["message", "arguments", "type", "name"])
+ `Message: ${event.message}\nURL: ${event.url}\nLine: ${event.lineNo}, Column: ${event.columnNo}\nStack: ${event.error.stack}`
);
}
});
@@ -111,7 +111,7 @@ window.addEventListener("error", error => {
//send error to back
function promptError(error) {
if (error instanceof Error) {
- error = error.message;
+ error = error.message + "\n" + error.stack;
}
ipcRenderer.sendSync("prompt-error:" + promptId, error);
@@ -124,20 +124,18 @@ function promptCancel() {
//transfer input data to back
function promptSubmit() {
- const dataElement = $("#data");
let data = null;
switch (promptOptions.type) {
case "input":
+ case "select":
data = dataElement.value;
break;
case "counter":
data = validateCounterInput(dataElement.value);
break;
- case "select":
- data = promptOptions.selectMultiple ?
- dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
- dataElement.value;
+ case "keybind":
+ data = dataElement.submit();
break;
default: //will never happen
return promptError(`Unhandled input type '${promptOptions.type}'`);
@@ -152,9 +150,6 @@ function promptCreateInput() {
dataElement.setAttribute("type", "text");
if (promptOptions.value) {
- if (promptOptions.type === "counter") {
- promptOptions.value = validateCounterInput(promptOptions.value);
- }
dataElement.value = promptOptions.value;
} else {
dataElement.value = "";
@@ -212,21 +207,50 @@ function promptCreateSelect() {
return dataElement;
}
+function promptCreateCounter(parentElement) {
+ if (promptOptions.counterOptions?.multiFire) {
+ document.onmouseup = () => {
+ if (nextTimeoutID) {
+ clearTimeout(nextTimeoutID)
+ nextTimeoutID = null;
+ }
+ };
+ }
+
+ promptOptions.value = validateCounterInput(promptOptions.value);
+
+ const dataElement = promptCreateInput();
+ dataElement.onkeypress = function isNumberKey(e) {
+ if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete")
+ return false;
+ return true;
+ }
+
+ dataElement.style.width = "unset";
+ dataElement.style["text-align"] = "center";
+
+ parentElement.append(createMinusButton(dataElement));
+ parentElement.append(dataElement);
+ parentElement.append(createPlusButton(dataElement));
+
+ return dataElement;
+}
+
let nextTimeoutID = null;
-/* Function execute callback in 3 accelerated intervals based on timer.
+/** Function execute callback in 3 accelerated intervals based on timer.
* Terminated from document.onmouseup() that is registered from promptCreateCounter()
- * @param {function} callback: function to execute
- * @param {object} timer: {
- * * time: First delay in miliseconds.
- * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
+ * @param {function} callback function to execute
+ * @param {object} timer {
+ * * time: First delay in miliseconds
* * scaleSpeed: Speed change per tick on first acceleration
- * }
- * @param {int} stepArgs: argument for callback representing Initial steps per click, default to 1
+ * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
+ * }
+ * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1
* steps starts to increase when speed is too fast to notice
- * @param {int} counter: used internally to decrease timer.limit
+ * @param {int} counter used internally to decrease timer.limit
*/
-function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 }, stepsArg = 1, counter = 0) {
+function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) {
callback(stepsArg);
const nextTimeout = timer.time;
@@ -241,9 +265,7 @@ function multiFire(callback, timer = { time: 500, scaleSpeed: 140, limit: 100 },
}
if (timer.time !== timer.limit) {
- timer.time = timer.time > timer.limit ?
- timer.time - timer.scaleSpeed :
- timer.limit;
+ timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit)
}
nextTimeoutID = setTimeout(
@@ -301,26 +323,9 @@ function createPlusButton(dataElement) {
return plusBtn;
}
-function promptCreateCounter() {
- if (promptOptions.counterOptions?.multiFire) {
- document.onmouseup = () => {
- if (nextTimeoutID) {
- clearTimeout(nextTimeoutID)
- nextTimeoutID = null;
- }
- };
- }
-
- const dataElement = promptCreateInput();
-
- dataElement.style.width = "unset";
- dataElement.style["text-align"] = "center";
-
- return dataElement;
-}
-
//validate counter
function validateCounterInput(input) {
+
const min = promptOptions.counterOptions?.minimum;
const max = promptOptions.counterOptions?.maximum;
//note that !min/max would proc if min/max are 0
@@ -334,3 +339,6 @@ function validateCounterInput(input) {
return input;
}
+
+module.exports.promptError = promptError;
+
From 8dc486f18fe02a218b149838dc7ab939ec1b698a Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Wed, 28 Apr 2021 02:51:19 +0300
Subject: [PATCH 44/52] remove local prompt
---
menu.js | 37 ---
providers/prompt/custom-titlebar.js | 14 --
providers/prompt/dark-prompt.css | 76 ------
providers/prompt/index.js | 170 --------------
providers/prompt/page/counter.js | 140 -----------
providers/prompt/page/keybind.js | 305 ------------------------
providers/prompt/page/prompt.css | 120 ----------
providers/prompt/page/prompt.html | 18 --
providers/prompt/page/prompt.js | 344 ----------------------------
providers/prompt/readme.md | 80 -------
10 files changed, 1304 deletions(-)
delete mode 100644 providers/prompt/custom-titlebar.js
delete mode 100644 providers/prompt/dark-prompt.css
delete mode 100644 providers/prompt/index.js
delete mode 100644 providers/prompt/page/counter.js
delete mode 100644 providers/prompt/page/keybind.js
delete mode 100644 providers/prompt/page/prompt.css
delete mode 100644 providers/prompt/page/prompt.html
delete mode 100644 providers/prompt/page/prompt.js
delete mode 100644 providers/prompt/readme.md
diff --git a/menu.js b/menu.js
index dddce721..0ab62c7f 100644
--- a/menu.js
+++ b/menu.js
@@ -6,7 +6,6 @@ const is = require("electron-is");
const { getAllPlugins } = require("./plugins/utils");
const config = require("./config");
-const prompt = require('./providers/prompt');
const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
label: label || plugin,
@@ -309,39 +308,3 @@ module.exports.setApplicationMenu = (win) => {
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
};
-
-const iconPath = path.join(__dirname, "assets", "youtube-music-tray.png");
-const example = `Example: "socks5://127.0.0.1:9999"`;
-function setProxy(item, win) {
- let options = {
- title: 'Set Proxy',
- label: 'Enter Proxy Address: (leave empty to disable)',
- value: config.get("options.proxy") || example,
- inputAttrs: {
- type: 'text'
- },
- type: 'input',
- icon: iconPath,
- customStylesheet: "dark",
- };
- //TODO: custom bar on prompt need testing on macOS
- if (!is.macOS()) {
- Object.assign(options, {
- frame: false,
- customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"),
- enableRemoteModule: true,
- height: 200,
- width: 450,
- });
- }
- prompt(options, win)
- .then(input => {
- if (input !== null && input !== example) {
- config.set("options.proxy", input);
- item.checked = input !== "";
- } else { //user pressed cancel
- item.checked = !item.checked; //reset checkbox
- }
- })
- .catch(console.error);
-}
diff --git a/providers/prompt/custom-titlebar.js b/providers/prompt/custom-titlebar.js
deleted file mode 100644
index c36ce5f5..00000000
--- a/providers/prompt/custom-titlebar.js
+++ /dev/null
@@ -1,14 +0,0 @@
-const customTitlebar = require("custom-electron-titlebar");
-
-module.exports = () => {
- const bar = new customTitlebar.Titlebar({
- backgroundColor: customTitlebar.Color.fromHex("#050505"),
- minimizable: false,
- maximizable: false,
- menu: null
- });
- const mainStyle = document.querySelector("#container").style;
- mainStyle.width = "100%";
- mainStyle.position = "fixed";
- mainStyle.border = "unset";
-};
diff --git a/providers/prompt/dark-prompt.css b/providers/prompt/dark-prompt.css
deleted file mode 100644
index 768b9e52..00000000
--- a/providers/prompt/dark-prompt.css
+++ /dev/null
@@ -1,76 +0,0 @@
-body {
- background-color: rgba(0, 0, 0, 0.3);
- background-image: linear-gradient(315deg, #200000 0%, #13253a 74%);
- color: whitesmoke;
-}
-
-#label {
- text-align: center;
-}
-
-#container {
- background: rgba(0, 0, 0, 0.7);
- box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- border-radius: 10px;
- border: 1px solid rgba(80, 0, 0, 0.4);
- overflow: hidden;
-}
-
-#data,
-.keybindData {
- background: unset;
- color: whitesmoke;
- border: 1px solid rgb(54, 54, 54);
-}
-
-#data:hover {
- border: 1px solid rgb(85, 85, 85);
-}
-
-#data:focus {
- outline: unset;
- border: 1px solid rgb(85, 85, 85);
-}
-
-#ok:hover,
-#ok:focus,
-#cancel:hover,
-#cancel:focus {
- outline: rgba(60, 0, 0, 0.4) solid 2px;
-}
-
-#ok,
-#cancel,
-.clearButton {
- background-color: rgb(0, 0, 0);
- color: whitesmoke;
-}
-
-/* For Counter Prompt */
-.minus,
-.plus {
- background: rgb(0, 0, 0);
-}
-
-/* For Select Prompt */
-option {
- background-color: #07070C;
-}
-
-/* For Keybind Prompt */
-.clearButton:focus {
- outline: none;
-}
-.clearButton:hover {
- background-color: rgb(5, 5, 5);
-}
-.keybindData:hover {
- border: 1px solid rgb(56, 0, 0);
-}
-
-.keybindData:focus {
- outline: 3px solid #1E0919;
- border: 1px solid rgb(56, 0, 0);
-}
diff --git a/providers/prompt/index.js b/providers/prompt/index.js
deleted file mode 100644
index a5c2230c..00000000
--- a/providers/prompt/index.js
+++ /dev/null
@@ -1,170 +0,0 @@
-const electron = require("electron");
-
-const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;
-const ipcMain = electron.ipcMain || electron.remote.ipcMain;
-const url = require("url");
-const path = require("path");
-
-const DEFAULT_WIDTH = 370;
-const DEFAULT_KEYBIND_WIDTH = 420;
-const DEFAULT_COUNTER_WIDTH = 300;
-const DEFAULT_HEIGHT = 150;
-const DEFAULT_KEYBIND_HEIGHT = options => (options.length * 40) + 100;
-
-function electronPrompt(options, parentWindow) {
- return new Promise((resolve, reject) => {
- //id used to ensure unique listeners per window
- const id = `${Date.now()}-${Math.random()}`;
-
- //custom options override default
- const options_ = Object.assign(
- {
- width: options?.type === "counter" ? DEFAULT_COUNTER_WIDTH : options?.type === "keybind" ? DEFAULT_KEYBIND_WIDTH : DEFAULT_WIDTH,
- height: options?.type === "keybind" && options?.keybindOptions ? DEFAULT_KEYBIND_HEIGHT(options.keybindOptions) : DEFAULT_HEIGHT,
- resizable: false,
- title: "Prompt",
- label: "Please input a value:",
- buttonLabels: null,
- alwaysOnTop: false,
- value: null,
- type: "input",
- selectOptions: null,
- keybindOptions: null,
- counterOptions: { minimum: null, maximum: null, multiFire: false },
- icon: null,
- useHtmlLabel: false,
- customStylesheet: null,
- menuBarVisible: false,
- skipTaskbar: true,
- frame: true,
- customScript: null,
- enableRemoteModule: false
- },
- options || {}
- );
-
-
-
- if (options_.customStylesheet === "dark") {
- options_.customStylesheet = require("path").join(__dirname, "dark-prompt.css");
- }
-
- for (let type of ["counter", "select", "keybind"]) {
- if (options_.type === type && (!options_[`${type}Options`] || typeof options_[`${type}Options`] !== "object")) {
- reject(new Error(`"${type}Options" must be an object if type = ${type}`));
- return;
- }
- }
-
- options_.minWidth = options?.minWidth || options?.width || options_.width;
- options_.minHeight = options?.minHeight || options?.height || options_.height;
-
- let promptWindow = new BrowserWindow({
- frame: options_.frame,
- width: options_.width,
- height: options_.height,
- minWidth: options_.minWidth,
- minHeight: options_.minHeight,
- resizable: options_.resizable,
- minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop,
- fullscreenable: options_.resizable,
- maximizable: options_.resizable,
- parent: parentWindow,
- skipTaskbar: options_.skipTaskbar,
- alwaysOnTop: options_.alwaysOnTop,
- useContentSize: options_.resizable,
- modal: Boolean(parentWindow),
- title: options_.title,
- icon: options_.icon || undefined,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
- enableRemoteModule: options_.enableRemoteModule
- }
- });
-
- promptWindow.setMenu(null);
- promptWindow.setMenuBarVisibility(options_.menuBarVisible);
-
- //called on exit
- const cleanup = () => {
- ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener);
- ipcMain.removeListener("prompt-post-data:" + id, postDataListener);
- ipcMain.removeListener("prompt-error:" + id, errorListener);
-
- if (promptWindow) {
- promptWindow.close();
- promptWindow = null;
- }
- };
-
- ///transfer options to front
- const getOptionsListener = event => {
- event.returnValue = JSON.stringify(options_);
- };
-
- //get input from front
- const postDataListener = (event, value) => {
- if (options_.type === "keybind" && value) {
- for (let i=0; i < value.length ;i++) {
- value[i] = JSON.parse(value[i])
- }
- }
- resolve(value);
- event.returnValue = null;
- cleanup();
- };
-
- const unresponsiveListener = () => {
- reject(new Error("Window was unresponsive"));
- cleanup();
- };
-
- //get error from front
- const errorListener = (event, message) => {
- reject(new Error(message));
- event.returnValue = null;
- cleanup();
- };
-
- //attach listeners
- ipcMain.on("prompt-get-options:" + id, getOptionsListener);
- ipcMain.on("prompt-post-data:" + id, postDataListener);
- ipcMain.on("prompt-error:" + id, errorListener);
- promptWindow.on("unresponsive", unresponsiveListener);
-
- promptWindow.on("closed", () => {
- promptWindow = null;
- cleanup();
- resolve(null);
- });
-
- //should never happen
- promptWindow.webContents.on("did-fail-load", (
- _event,
- errorCode,
- errorDescription,
- validatedURL
- ) => {
- const log = {
- error: "did-fail-load",
- errorCode,
- errorDescription,
- validatedURL
- };
- reject(new Error("prompt.html did-fail-load, log:\n" + log.toString()));
- });
-
- const promptUrl = url.format({
- protocol: "file",
- slashes: true,
- pathname: path.join(__dirname, "page", "prompt.html"),
- hash: id
- });
-
- //Finally, load prompt
- promptWindow.loadURL(promptUrl);
- });
-}
-
-module.exports = electronPrompt;
diff --git a/providers/prompt/page/counter.js b/providers/prompt/page/counter.js
deleted file mode 100644
index 6f773d97..00000000
--- a/providers/prompt/page/counter.js
+++ /dev/null
@@ -1,140 +0,0 @@
-const { promptCreateInput } = require("./prompt");
-
-module.exports = { promptCreateCounter , validateCounterInput }
-
-let options;
-
-
-function promptCreateCounter(promptOptions, parentElement) {
- options = promptOptions;
- if (options.counterOptions?.multiFire) {
- document.onmouseup = () => {
- if (nextTimeoutID) {
- clearTimeout(nextTimeoutID)
- nextTimeoutID = null;
- }
- };
- }
-
- options.value = validateCounterInput(options.value);
-
- const dataElement = promptCreateInput();
- dataElement.onkeypress = function isNumberKey(e) {
- if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete")
- return false;
- return true;
- }
-
- dataElement.style.width = "unset";
- dataElement.style["text-align"] = "center";
-
- parentElement.append(createMinusButton(dataElement));
- parentElement.append(dataElement);
- parentElement.append(createPlusButton(dataElement));
-
- return dataElement;
-}
-
-let nextTimeoutID = null;
-
-/** Function execute callback in 3 accelerated intervals based on timer.
- * Terminated from document.onmouseup() that is registered from promptCreateCounter()
- * @param {function} callback function to execute
- * @param {object} timer {
- * * time: First delay in miliseconds
- * * scaleSpeed: Speed change per tick on first acceleration
- * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
- * }
- * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1
- * steps starts to increase when speed is too fast to notice
- * @param {int} counter used internally to decrease timer.limit
- */
-function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) {
- callback(stepsArg);
-
- const nextTimeout = timer.time;
-
- if (counter > 20) {
- counter = 0 - stepsArg;
- if (timer.limit > 1) {
- timer.limit /= 2;
- } else {
- stepsArg *= 2;
- }
- }
-
- if (timer.time !== timer.limit) {
- timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit)
- }
-
- nextTimeoutID = setTimeout(
- multiFire, //callback
- nextTimeout, //timer
- //multiFire args:
- callback,
- timer,
- stepsArg,
- counter + 1
- );
-}
-
-function createMinusButton(dataElement) {
- function doMinus(steps) {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps);
- }
-
- const minusBtn = document.createElement("span");
- minusBtn.textContent = "-";
- minusBtn.classList.add("minus");
-
- if (options.counterOptions?.multiFire) {
- minusBtn.onmousedown = () => {
- multiFire(doMinus);
- };
- } else {
- minusBtn.onmousedown = () => {
- doMinus();
- };
- }
-
- return minusBtn;
-}
-
-function createPlusButton(dataElement) {
- function doPlus(steps) {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps);
- }
-
- const plusBtn = document.createElement("span");
- plusBtn.textContent = "+";
- plusBtn.classList.add("plus");
-
- if (options.counterOptions?.multiFire) {
- plusBtn.onmousedown = () => {
- multiFire(doPlus);
- };
- } else {
- plusBtn.onmousedown = () => {
- doPlus();
- };
- }
-
- return plusBtn;
-}
-
-//validate counter
-function validateCounterInput(input) {
-
- const min = options.counterOptions?.minimum;
- const max = options.counterOptions?.maximum;
- //note that !min/max would proc if min/max are 0
- if (min !== null && min !== undefined && input < min) {
- return min;
- }
-
- if (max !== null && max !== undefined && input > max) {
- return max;
- }
-
- return input;
-}
diff --git a/providers/prompt/page/keybind.js b/providers/prompt/page/keybind.js
deleted file mode 100644
index 2406f736..00000000
--- a/providers/prompt/page/keybind.js
+++ /dev/null
@@ -1,305 +0,0 @@
-/* HTML
-
-
- Example
-
-
- Clear
-
-
-
-*/
-/* CSS
-
-div.keybind {
- display: grid;
- grid-template-columns: max-content max-content max-content;
- grid-gap: 5px;
-}
-
-div.keybind button {
- width: auto;
-}
-
-div.keybind label {
- text-align: right;
-}
-
-div.keybind label:after {
- content: ":";
-}
-
-*/
-const { promptError } = require("./prompt")
-
-class KeybindGetter {
- value = null;
- modifiers = null;
- key = "";
- label = null;
- txt = null;
- clearButton = null;
-
- constructor(options, parentElement) {
- if (!options.label || !options.value) {
- promptError("keybind option must contain label and value");
- return;
- }
-
- this.value = options.value
- this.modifiers = new Set();
- this.key = "";
-
- this.label = document.createElement("label");
- this.label.classList.add("keybindLabel");
-
- this.txt = document.createElement("input");
- this.txt.setAttribute('readonly', true);
- this.txt.classList.add("keybindData");
-
- this.clearButton = document.createElement("button");
- this.clearButton.classList.add("clearButton");
- this.clearButton.textContent = "Clear";
- this.clearButton.onclick = (e) => e.preventDefault();
-
- parentElement.append(this.label, this.txt, this.clearButton);
-
- this.setup(options);
- if (options.default) {
- this.setDefault(options.default)
- }
- }
-
- focus() {
- this.txt.focus();
- }
-
- output() {
- const output = {value: this.value, accelerator: this.txt.value.replaceAll(" ", "")}
- return JSON.stringify(output);
- }
-
- updateText() {
- let result = "";
- for (let modifier of this.modifiers) {
- result += modifier + " + ";
- }
- this.txt.value = result + this.key;
- }
-
- setDefault(defaultValue) {
- const accelerator = parseAccelerator(defaultValue).split("+");
- for (let key of accelerator) {
- if (isModifier(key))
- this.modifiers.add(key);
- else
- this.key = key;
- }
- this.updateText();
- }
- clear() {
- this.modifiers.clear();
- this.key = "";
- this.txt.value = "";
- }
-
- setup(options) {
- this.txt.addEventListener("keydown", (event) => {
- event.preventDefault();
- if (event.repeat) {
- return
- }
- let key = event.code || event.key;
- if (key in virtualKeyCodes)
- key = virtualKeyCodes[event.code];
- else {
- console.log('Error, key "' + event.code + '" was not found');
- return;
- }
-
- if (isModifier(key)) {
- if (this.modifiers.size < 3)
- this.modifiers.add(key);
- } else { // is key
- this.key = key;
- }
- this.updateText();
- });
-
- this.clearButton.addEventListener("click", () => {
- this.clear()
- });
- this.label.textContent = options.label + " ";
- }
-}
-
-class keybindContainer {
- elements = [];
-
- constructor(options, parentElement) {
- parentElement.classList.add("keybind");
- this.elements = options.map(option => new KeybindGetter(option, parentElement));
- document.querySelector("#buttons").style["padding-top"] = "20px";
- }
-
- focus() {
- if (this.elements.length > 0)
- this.elements[0].focus();
- }
-
- submit() {
- return this.elements.map(element => element.output());
- }
-}
-
-function parseAccelerator(a) {
- let accelerator = a.toString();
-
- if (process.platform !== 'darwin') {
- accelerator = accelerator.replace(/(Cmd)|(Command)/gi, '');
- } else {
- accelerator = accelerator.replace(/(Ctrl)|(Control)/gi, '');
- }
-
- accelerator = accelerator.replace(/(Or)/gi, '');
-
- return accelerator;
-}
-
-function isModifier(key) {
- for (let modifier of ["Shift", "Control", "Ctrl", "Command", "Cmd", "Alt", "AltGr", "Super"]) {
- if (key === modifier)
- return true;
- }
- return false;
-}
-
-const virtualKeyCodes = {
- ShiftLeft: "Shift",
- ShiftRight: "Shift",
- ControlLeft: "Ctrl",
- ControlRight: "Ctrl",
- AltLeft: "Alt",
- AltRight: "Alt",
- MetaLeft: "Super",
- MetaRight: "Super",
- NumLock: "NumLock",
- NumpadDivide: "NumDiv",
- NumpadMultiply: "NumMult",
- NumpadSubtract: "NumSub",
- NumpadAdd: "NumAdd",
- NumpadDecimal: "NumDec ",
- Numpad0: "Num0",
- Numpad1: "Num1",
- Numpad2: "Num2",
- Numpad3: "Num3",
- Numpad4: "Num4",
- Numpad5: "Num5",
- Numpad6: "Num6",
- Numpad7: "Num7",
- Numpad8: "Num8",
- Numpad9: "Num9",
- Digit0: "0",
- Digit1: "1",
- Digit2: "2",
- Digit3: "3",
- Digit4: "4",
- Digit5: "5",
- Digit6: "6",
- Digit7: "7",
- Digit8: "8",
- Digit9: "9",
- Minus: "-",
- Equal: "=",
- KeyQ: "Q",
- KeyW: "W",
- KeyE: "E",
- KeyR: "R",
- KeyT: "T",
- KeyY: "Y",
- KeyU: "U",
- KeyI: "I",
- KeyO: "O",
- KeyP: "P",
- KeyA: "A",
- KeyS: "S",
- KeyD: "D",
- KeyF: "F",
- KeyG: "G",
- KeyH: "H",
- KeyJ: "J",
- KeyK: "K",
- KeyL: "L",
- KeyZ: "Z",
- KeyX: "X",
- KeyC: "C",
- KeyV: "V",
- KeyB: "B",
- KeyN: "N",
- KeyM: "M",
- BracketLeft: "[",
- BracketRight: "]",
- Semicolon: ";",
- Quote: "'",
- Backquote: '"',
- Backslash: "\\",
- Comma: ",",
- Period: "'.'",
- Slash: "/",
- plus: '+',
- Space: "Space",
- Tab: "Tab",
- Backspace: "Backspace",
- Delete: "Delete",
- Insert: "Insert",
- Return: "Return",
- Enter: "Enter",
- ArrowUp: "Up",
- ArrowDown: "Down",
- ArrowLeft: "Left",
- ArrowRight: "Right",
- Home: "Home",
- End: "End",
- PageUp: "PageUp",
- PageDown: "PageDown",
- Escape: "Escape",
- AudioVolumeUp: "VolumeUp",
- AudioVolumeDown: "VolumeDown",
- AudioVolumeMute: "VolumeMute",
- MediaTrackNext: "MediaNextTrack",
- MediaTrackPrevious: "MediaPreviousTrack",
- MediaStop: "MediaStop",
- MediaPlayPause: "MediaPlayPause",
- ScrollLock: "ScrollLock",
- PrintScreen: "PrintScreen",
- F1: "F1",
- F2: "F2",
- F3: "F3",
- F4: "F4",
- F5: "F5",
- F6: "F6",
- F7: "F7",
- F8: "F8",
- F9: "F9",
- F10: "F10",
- F11: "F11",
- F12: "F12",
- F13: "F13",
- F14: "F14",
- F15: "F15",
- F16: "F16",
- F17: "F17",
- F18: "F18",
- F19: "F19",
- F20: "F20",
- F21: "F21",
- F22: "F22",
- F23: "F23",
- F24: "F24",
-};
-
-
-
-module.exports = function promptCreateKeybind(options, parentElement) {
- return new keybindContainer(options, parentElement);
-}
diff --git a/providers/prompt/page/prompt.css b/providers/prompt/page/prompt.css
deleted file mode 100644
index 6e52379a..00000000
--- a/providers/prompt/page/prompt.css
+++ /dev/null
@@ -1,120 +0,0 @@
-body {
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
- Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial,
- sans-serif;
- line-height: 1.5em;
- color: #333;
- background-color: #fff;
- overflow-y: hidden;
-}
-
-::-webkit-scrollbar {
- width: 0 !important;
- display: none;
-}
-
-#container {
- align-items: center;
- justify-content: center;
- display: flex;
- height: 100%;
- overflow-y: hidden;
-}
-
-#form {
- width: 100%;
- padding-top: 0.5em;
-}
-
-#label {
- max-width: 100%;
- max-height: 100%;
- margin-bottom: 0.8em;
- padding: 0 0.5em;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-#data {
- border-radius: 2px;
- background: #fff;
- width: 90%;
- padding: 0.4em 0.5em;
- border: 1px solid black;
- min-height: 2em;
- margin: 0 0 1.2em;
-}
-
-select#data {
- height: 2em;
-}
-
-#data-container {
- text-align: center;
-}
-
-#buttons {
- text-align: right;
- padding: 0 0.5em 0 0;
-}
-
-#buttons > button,
-#buttons > input[type="submit"] {
- border-radius: 2px;
- border: 0;
- margin: 0 0 0 0.5em;
- font-size: 0.8em;
- line-height: 1em;
- padding: 0.6em 1em;
-}
-
-#ok {
- background-color: #3879d9;
- color: white;
-}
-
-#cancel {
- background-color: #ddd;
- color: black;
-}
-
-/* Counter mode */
-span {
- cursor: pointer;
-}
-.minus,
-.plus {
- user-select: none;
- width: 20px;
- height: 20px;
- background: #f2f2f2;
- border-radius: 4px;
- padding: 8px 5px 8px 5px;
- border: 1px solid #ddd;
- display: inline-block;
- vertical-align: middle;
- text-align: center;
-}
-
-/** Keybind mode */
-div.keybind {
- display: grid;
- grid-template-columns: max-content max-content max-content;
- row-gap: 20px;
- column-gap: 10px;
- margin: auto 0;
- justify-content: center;
- }
-
- div.keybind button {
- width: auto;
- }
-
- div.keybind label {
- text-align: right;
- }
-
- div.keybind label:after {
- content: ":";
- }
\ No newline at end of file
diff --git a/providers/prompt/page/prompt.html b/providers/prompt/page/prompt.html
deleted file mode 100644
index cdbfa544..00000000
--- a/providers/prompt/page/prompt.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/providers/prompt/page/prompt.js b/providers/prompt/page/prompt.js
deleted file mode 100644
index e09816d3..00000000
--- a/providers/prompt/page/prompt.js
+++ /dev/null
@@ -1,344 +0,0 @@
-const fs = require("fs");
-const { ipcRenderer } = require("electron");
-let promptId = null;
-let promptOptions = null;
-let dataElement = null;
-
-function $(selector) { return document.querySelector(selector); }
-
-document.addEventListener("DOMContentLoaded", promptRegister);
-
-function promptRegister() {
-
- //get custom session id
- promptId = document.location.hash.replace("#", "");
-
- //get options from back
- try {
- promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
- } catch (error) {
- return promptError(error);
- }
-
- //set label
- if (promptOptions.useHtmlLabel) {
- $("#label").innerHTML = promptOptions.label;
- } else {
- $("#label").textContent = promptOptions.label;
- }
-
- //set button label
- if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
- $("#ok").textContent = promptOptions.buttonLabels.ok;
- }
-
- if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
- $("#cancel").textContent = promptOptions.buttonLabels.cancel;
- }
-
- //inject custom stylesheet from options
- if (promptOptions.customStylesheet) {
- try {
- const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
- if (customStyleContent) {
- const customStyle = document.createElement("style");
- customStyle.setAttribute("rel", "stylesheet");
- customStyle.append(document.createTextNode(customStyleContent));
- document.head.append(customStyle);
- }
- } catch (error) {
- return promptError(error);
- }
- }
-
- //add button listeners
- $("#form").addEventListener("submit", promptSubmit);
- $("#cancel").addEventListener("click", promptCancel);
-
- //create input/select/counter/keybind
- const dataContainerElement = $("#data-container");
-
- switch (promptOptions.type) {
- case "counter":
- dataElement = promptCreateCounter(dataContainerElement);
- break;
- case "input":
- dataElement = promptCreateInput();
- break;
- case "select":
- dataElement = promptCreateSelect();
- break;
- case "keybind":
- dataElement = require("./keybind")(promptOptions.keybindOptions, dataContainerElement);
- break;
- default:
- return promptError(`Unhandled input type '${promptOptions.type}'`);
- }
-
- if (promptOptions.type != "keybind") {
- dataElement.setAttribute("id", "data");
-
- if (promptOptions.type !== "counter") {
- dataContainerElement.append(dataElement);
- }
- }
-
- dataElement.focus();
-
- if (promptOptions.type !== "select" && promptOptions.type !== "keybind") {
- dataElement.select();
- }
-
- //load custom script from options
- if (promptOptions.customScript) {
- try {
- const customScript = require(promptOptions.customScript);
- customScript();
- } catch (error) {
- return promptError(error);
- }
- }
-}
-
-window.addEventListener("error", event => {
- if (promptId) {
- promptError("An error has occured on the prompt window: \n" +
- `Message: ${event.message}\nURL: ${event.url}\nLine: ${event.lineNo}, Column: ${event.columnNo}\nStack: ${event.error.stack}`
- );
- }
-});
-
-//send error to back
-function promptError(error) {
- if (error instanceof Error) {
- error = error.message + "\n" + error.stack;
- }
-
- ipcRenderer.sendSync("prompt-error:" + promptId, error);
-}
-
-//send to back: input=null
-function promptCancel() {
- ipcRenderer.sendSync("prompt-post-data:" + promptId, null);
-}
-
-//transfer input data to back
-function promptSubmit() {
- let data = null;
-
- switch (promptOptions.type) {
- case "input":
- case "select":
- data = dataElement.value;
- break;
- case "counter":
- data = validateCounterInput(dataElement.value);
- break;
- case "keybind":
- data = dataElement.submit();
- break;
- default: //will never happen
- return promptError(`Unhandled input type '${promptOptions.type}'`);
- }
-
- ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
-}
-
-//creates input box
-function promptCreateInput() {
- const dataElement = document.createElement("input");
- dataElement.setAttribute("type", "text");
-
- if (promptOptions.value) {
- dataElement.value = promptOptions.value;
- } else {
- dataElement.value = "";
- }
-
- //insert custom input attributes if in options
- if (promptOptions.inputAttrs && typeof (promptOptions.inputAttrs) === "object") {
- for (const k in promptOptions.inputAttrs) {
- if (!Object.prototype.hasOwnProperty.call(promptOptions.inputAttrs, k)) {
- continue;
- }
-
- dataElement.setAttribute(k, promptOptions.inputAttrs[k]);
- }
- }
-
- //Cancel/Exit on 'Escape'
- dataElement.addEventListener("keyup", event => {
- if (event.key === "Escape") {
- promptCancel();
- }
- });
-
- //Confirm on 'Enter'
- dataElement.addEventListener("keypress", event => {
- if (event.key === "Enter") {
- event.preventDefault();
- $("#ok").click();
- }
- });
-
- return dataElement;
-}
-
-//create multiple select
-function promptCreateSelect() {
- const dataElement = document.createElement("select");
- let optionElement;
-
- for (const k in promptOptions.selectOptions) {
- if (!Object.prototype.hasOwnProperty.call(promptOptions.selectOptions, k)) {
- continue;
- }
-
- optionElement = document.createElement("option");
- optionElement.setAttribute("value", k);
- optionElement.textContent = promptOptions.selectOptions[k];
- if (k === promptOptions.value) {
- optionElement.setAttribute("selected", "selected");
- }
-
- dataElement.append(optionElement);
- }
-
- return dataElement;
-}
-
-function promptCreateCounter(parentElement) {
- if (promptOptions.counterOptions?.multiFire) {
- document.onmouseup = () => {
- if (nextTimeoutID) {
- clearTimeout(nextTimeoutID)
- nextTimeoutID = null;
- }
- };
- }
-
- promptOptions.value = validateCounterInput(promptOptions.value);
-
- const dataElement = promptCreateInput();
- dataElement.onkeypress = function isNumberKey(e) {
- if (Number.isNaN(parseInt(e.key)) && e.key !== "Backspace" && e.key !== "Delete")
- return false;
- return true;
- }
-
- dataElement.style.width = "unset";
- dataElement.style["text-align"] = "center";
-
- parentElement.append(createMinusButton(dataElement));
- parentElement.append(dataElement);
- parentElement.append(createPlusButton(dataElement));
-
- return dataElement;
-}
-
-let nextTimeoutID = null;
-
-/** Function execute callback in 3 accelerated intervals based on timer.
- * Terminated from document.onmouseup() that is registered from promptCreateCounter()
- * @param {function} callback function to execute
- * @param {object} timer {
- * * time: First delay in miliseconds
- * * scaleSpeed: Speed change per tick on first acceleration
- * * limit: First Speed Limit, gets divided by 2 after $20 calls. $number change exponentially
- * }
- * @param {int} stepArgs argument for callback representing Initial steps per click, default to 1
- * steps starts to increase when speed is too fast to notice
- * @param {int} counter used internally to decrease timer.limit
- */
-function multiFire(callback, timer = { time: 300, scaleSpeed: 100, limit: 100 }, stepsArg = 1, counter = 0) {
- callback(stepsArg);
-
- const nextTimeout = timer.time;
-
- if (counter > 20) {
- counter = 0 - stepsArg;
- if (timer.limit > 1) {
- timer.limit /= 2;
- } else {
- stepsArg *= 2;
- }
- }
-
- if (timer.time !== timer.limit) {
- timer.time = Math.max(timer.time - timer.scaleSpeed, timer.limit)
- }
-
- nextTimeoutID = setTimeout(
- multiFire, //callback
- nextTimeout, //timer
- //multiFire args:
- callback,
- timer,
- stepsArg,
- counter + 1
- );
-}
-
-function createMinusButton(dataElement) {
- function doMinus(steps) {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) - steps);
- }
-
- const minusBtn = document.createElement("span");
- minusBtn.textContent = "-";
- minusBtn.classList.add("minus");
-
- if (promptOptions.counterOptions?.multiFire) {
- minusBtn.onmousedown = () => {
- multiFire(doMinus);
- };
- } else {
- minusBtn.onmousedown = () => {
- doMinus();
- };
- }
-
- return minusBtn;
-}
-
-function createPlusButton(dataElement) {
- function doPlus(steps) {
- dataElement.value = validateCounterInput(parseInt(dataElement.value) + steps);
- }
-
- const plusBtn = document.createElement("span");
- plusBtn.textContent = "+";
- plusBtn.classList.add("plus");
-
- if (promptOptions.counterOptions?.multiFire) {
- plusBtn.onmousedown = () => {
- multiFire(doPlus);
- };
- } else {
- plusBtn.onmousedown = () => {
- doPlus();
- };
- }
-
- return plusBtn;
-}
-
-//validate counter
-function validateCounterInput(input) {
-
- const min = promptOptions.counterOptions?.minimum;
- const max = promptOptions.counterOptions?.maximum;
- //note that !min/max would proc if min/max are 0
- if (min !== null && min !== undefined && input < min) {
- return min;
- }
-
- if (max !== null && max !== undefined && input > max) {
- return max;
- }
-
- return input;
-}
-
-module.exports.promptError = promptError;
-
diff --git a/providers/prompt/readme.md b/providers/prompt/readme.md
deleted file mode 100644
index 613b4676..00000000
--- a/providers/prompt/readme.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# Prompt Component Documentation
-
-Simplest Prompt with no stylesheet:
-
-## Usage
-```js
-prompt([options, parentBrowserWindow]).then(...).catch(...)
-```
-Promise resolve returns input
-
-If user presses cancel/exit window, input = null;
-
-On error, Prompise reject returns custom error message
-## Example
-
-```js
-const prompt = require('./providers/prompt');
-
-prompt({
- title: 'Prompt example',
- label: 'URL:',
- value: 'http://example.org',
- inputAttrs: {
- type: 'url'
- },
- type: 'input'
-})
-.then((r) => {
- if(r === null) {
- console.log('user cancelled');
- } else {
- console.log('result', r);
- }
-})
-.catch(console.error);
-```
-
-### Options object (optional)
-
-| Key | Explanation |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| title | (optional, string) The title of the prompt window. Defaults to 'Prompt'. |
-| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. |
-| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. |
-| value | (optional, string) The default value for the input field. Defaults to null. |
-| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. |
-| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> ` `. Used if the type is 'input'
-| counterOptions | (optional, object) minimum and maximum of counter, and if continuous input is enabled. format: `{minimum: %int%, maximum: %int%, multiFire: %boolean%`. min+max values defaults to null and multiFire defaults to false. |
-| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
-| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
-| width | (optional, integer) The width of the prompt window. Defaults to 370. |
-| minWidth | (optional, integer) The minimum allowed width for the prompt window. Default to width if specified or default_width(370). | |
-| height | (optional, integer) The height of the prompt window. Defaults to 130. |
-| minHeight | (optional, integer) The minimum allowed height for the prompt window. Same default value as height. |
-| resizable | (optional, boolean) Whether the prompt window can be resized or not (also sets useContentSize). Defaults to false. |
-| alwaysOnTop | (optional, boolean) Whether the window should always stay on top of other windows. Defaults to false |
-| icon | (optional, string) The path to an icon image to use in the title bar. Defaults to null and uses electron's icon. |
-| customStylesheet | (optional, string) The local path of a CSS file to customize the style of the prompt window, you can use just "dark" to use the premade dark skin. Defaults to null. |
-| menuBarVisible | (optional, boolean) Whether to show the menubar or not. Defaults to false. |
-| skipTaskbar | (optional, boolean) Whether to show the prompt window icon in taskbar. Defaults to true. |
-| frame | (optional, boolean) Wether to create prompt with frame. Defaults to true. |
-| customScript | (optional, string) The local path of a JS file to run on preload. Defaults to null. |
-| enableRemoteModule | (optional, boolean) Wether the prompt window have remote modules activated, Defaults to false. |
-
-If not supplied, it uses the defaults listed in the table above.
-
-### parentBrowserWindow (optional)
-
-The window in which to display the prompt on. If not supplied, the parent window of the prompt will be null.
-
-### customScript (optional)
-
-Create the script with the following template:
-
-```node
-module.exports = () => {
- // This function will be called as a preload script
- // So you can use front features like `document.querySelector`
-};
-```
From 0adb36cfb87102944b5ded57f745ff6ea75a7cf8 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Wed, 28 Apr 2021 03:08:25 +0300
Subject: [PATCH 45/52] leave debug for next PR
---
index.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/index.js b/index.js
index 82ba695d..80ba9efe 100644
--- a/index.js
+++ b/index.js
@@ -38,9 +38,7 @@ if (config.get("options.proxy")) {
}
// Adds debug features like hotkeys for triggering dev tools and reload
-require("electron-debug")({
- showDevTools: false //disable automatic devTools on new window
-});
+require("electron-debug")();
// Prevent window being garbage collected
let mainWindow;
From b77643b92899fef607bae690e48a8b0354ee81d3 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Wed, 28 Apr 2021 03:54:59 +0300
Subject: [PATCH 46/52] remove proxy from menu
---
menu.js | 8 --------
1 file changed, 8 deletions(-)
diff --git a/menu.js b/menu.js
index 0ab62c7f..957d2b2b 100644
--- a/menu.js
+++ b/menu.js
@@ -143,14 +143,6 @@ const mainMenuTemplate = (win) => [
{
label: "Advanced options",
submenu: [
- {
- label: "Proxy",
- type: "checkbox",
- checked: !!config.get("options.proxy"),
- click: (item) => {
- setProxy(item, win);
- }
- },
{
label: "Disable hardware acceleration",
type: "checkbox",
From 442aafd2c56972614ba1f634c39a803a7f38db39 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sun, 2 May 2021 23:25:20 +0300
Subject: [PATCH 47/52] remove redundant dialog import
---
index.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/index.js b/index.js
index 80ba9efe..75d85348 100644
--- a/index.js
+++ b/index.js
@@ -2,7 +2,6 @@
const path = require("path");
const electron = require("electron");
-const { dialog } = require("electron");
const is = require("electron-is");
const unhandled = require("electron-unhandled");
const { autoUpdater } = require("electron-updater");
@@ -327,7 +326,7 @@ function showUnresponsiveDialog(win, details) {
if (!!details) {
console.log("Unresponsive Error!\n"+JSON.stringify(details, null, "\t"))
}
- dialog.showMessageBox(win, {
+ electron.dialog.showMessageBox(win, {
type: "error",
title: "Window Unresponsive",
message: "The Application is Unresponsive",
From 1f69048c866a703c03c755573162ce1dc5d28b17 Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 2 May 2021 23:25:34 +0300
Subject: [PATCH 48/52] minify switch case
Co-authored-by: th-ch
---
index.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/index.js b/index.js
index 80ba9efe..681b5a8e 100644
--- a/index.js
+++ b/index.js
@@ -341,7 +341,6 @@ function showUnresponsiveDialog(win, details) {
case 2:
app.quit();
break;
- case 0:
default:
break;
}
From 02d16ca51084c1343bb0fb273f775971d2b844ee Mon Sep 17 00:00:00 2001
From: Araxeus <78568641+Araxeus@users.noreply.github.com>
Date: Sun, 2 May 2021 23:25:46 +0300
Subject: [PATCH 49/52] fix typo
Co-authored-by: th-ch
---
index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/index.js b/index.js
index 681b5a8e..9ee68492 100644
--- a/index.js
+++ b/index.js
@@ -331,7 +331,7 @@ function showUnresponsiveDialog(win, details) {
type: "error",
title: "Window Unresponsive",
message: "The Application is Unresponsive",
- details: "We are sorry for the inconveniance! please choose what to do:",
+ details: "We are sorry for the inconvenience! please choose what to do:",
buttons: ["Wait", "Relaunch", "Quit"],
cancelId: 0
}).then( result => {
From 8f766bcbaad8da0ea3ec6f22e56fb9f893f27867 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Sun, 2 May 2021 23:41:16 +0300
Subject: [PATCH 50/52] resolve merge conflict
---
plugins/taskbar-mediacontrol/back.js | 86 +++++++++++++---------------
1 file changed, 41 insertions(+), 45 deletions(-)
diff --git a/plugins/taskbar-mediacontrol/back.js b/plugins/taskbar-mediacontrol/back.js
index a8133539..46cb399e 100644
--- a/plugins/taskbar-mediacontrol/back.js
+++ b/plugins/taskbar-mediacontrol/back.js
@@ -2,57 +2,53 @@ const getSongControls = require('../../providers/song-controls');
const getSongInfo = require('../../providers/song-info');
const path = require('path');
+let controls;
+let currentSongInfo;
+
module.exports = win => {
- win.hide = function () {
- win.minimize();
- win.setSkipTaskbar(true);
- };
-
- const show = win.show;
- win.show = function () {
- win.restore();
- win.focus();
- win.setSkipTaskbar(false);
- show.apply(win);
- };
-
- win.isVisible = function () {
- return !win.isMinimized();
- };
-
const registerCallback = getSongInfo(win);
- const {playPause, next, previous} = getSongControls(win);
+ const { playPause, next, previous } = getSongControls(win);
+ controls = { playPause, next, previous };
- // If the page is ready, register the callback
- win.once('ready-to-show', () => {
- registerCallback(songInfo => {
- // Wait for song to start before setting thumbar
- if (songInfo.title === '') {
- return;
- }
-
- // Win32 require full rewrite of components
- win.setThumbarButtons([
- {
- tooltip: 'Previous',
- icon: get('backward.png'),
- click() {previous(win.webContents);}
- }, {
- tooltip: 'Play/Pause',
- // Update icon based on play state
- icon: songInfo.isPaused ? get('play.png') : get('pause.png'),
- click() {playPause(win.webContents);}
- }, {
- tooltip: 'Next',
- icon: get('forward.png'),
- click() {next(win.webContents);}
- }
- ]);
- });
+ registerCallback(songInfo => {
+ //update currentsonginfo for win.on('show')
+ currentSongInfo = songInfo;
+ // update thumbar
+ setThumbar(win, songInfo);
});
+
+ // need to set thumbar again after win.show
+ win.on("show", () => {
+ setThumbar(win, currentSongInfo)
+ })
};
+function setThumbar(win, songInfo) {
+ // Wait for song to start before setting thumbar
+ if (!songInfo?.title) {
+ return;
+ }
+
+ // Win32 require full rewrite of components
+ win.setThumbarButtons([
+ {
+ tooltip: 'Previous',
+ icon: get('backward.png'),
+ click() { controls.previous(win.webContents); }
+ }, {
+ tooltip: 'Play/Pause',
+ // Update icon based on play state
+ icon: songInfo.isPaused ? get('play.png') : get('pause.png'),
+ click() { controls.playPause(win.webContents); }
+ }, {
+ tooltip: 'Next',
+ icon: get('forward.png'),
+ click() { controls.next(win.webContents); }
+ }
+ ]);
+}
+
// Util
function get(file) {
- return path.join(__dirname,"assets", file);
+ return path.join(__dirname, "assets", file);
}
From d5b9e3c96029922812933350b655bd89de45ddcb Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Tue, 4 May 2021 01:22:47 +0300
Subject: [PATCH 51/52] stringify did-fail-load error directly preload
front-logger simplify front-logger
---
index.js | 6 +++---
preload.js | 3 +--
providers/front-logger.js | 8 +++-----
3 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/index.js b/index.js
index e28607c1..8c98e2c9 100644
--- a/index.js
+++ b/index.js
@@ -168,7 +168,7 @@ app.once("browser-window-created", (event, win) => {
frameProcessId,
frameRoutingId,
) => {
- const log = {
+ const log = JSON.stringify({
error: "did-fail-load",
event,
errorCode,
@@ -177,9 +177,9 @@ app.once("browser-window-created", (event, win) => {
isMainFrame,
frameProcessId,
frameRoutingId,
- };
+ }, null, "\t");
if (is.dev()) {
- console.log(log.toString());
+ console.log(log);
}
win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html"));
diff --git a/preload.js b/preload.js
index 74860cec..e0ce9ffe 100644
--- a/preload.js
+++ b/preload.js
@@ -34,8 +34,7 @@ document.addEventListener("DOMContentLoaded", () => {
fileExists(songInfoProviderPath, require(songInfoProviderPath));
// inject front logger
- const loggerPath = path.join(__dirname, "providers", "front-logger.js")
- fileExists(loggerPath, require(loggerPath));
+ require("./providers/front-logger")();
// Add action for reloading
global.reload = () =>
diff --git a/providers/front-logger.js b/providers/front-logger.js
index 210e3ff8..986cbb6f 100644
--- a/providers/front-logger.js
+++ b/providers/front-logger.js
@@ -1,11 +1,9 @@
const { ipcRenderer } = require("electron");
function logToString(log) {
- let string = (typeof log === "string") ? log : log.toString();
- if (!string || string.includes("[object Object]")) {
- string = JSON.stringify(log, null, "\t");
- }
- return string;
+ return (typeof log === "string") ?
+ log :
+ JSON.stringify(log, null, "\t");
}
module.exports = () => {
From fb81e1bdd5fd15dd97706eb0799b45966f7d9db1 Mon Sep 17 00:00:00 2001
From: Araxeus
Date: Tue, 4 May 2021 02:04:17 +0300
Subject: [PATCH 52/52] ignore did-fail-load error code `-3` bug with
in-app-menu
---
index.js | 9 +++++----
providers/front-logger.js | 2 +-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/index.js b/index.js
index 8c98e2c9..81fd45b5 100644
--- a/index.js
+++ b/index.js
@@ -160,7 +160,7 @@ app.once("browser-window-created", (event, win) => {
loadPlugins(win);
win.webContents.on("did-fail-load", (
- event,
+ _event,
errorCode,
errorDescription,
validatedURL,
@@ -170,7 +170,6 @@ app.once("browser-window-created", (event, win) => {
) => {
const log = JSON.stringify({
error: "did-fail-load",
- event,
errorCode,
errorDescription,
validatedURL,
@@ -181,8 +180,10 @@ app.once("browser-window-created", (event, win) => {
if (is.dev()) {
console.log(log);
}
- win.webContents.send("log", log);
- win.webContents.loadFile(path.join(__dirname, "error.html"));
+ 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.on("will-prevent-unload", (event) => {
diff --git a/providers/front-logger.js b/providers/front-logger.js
index 986cbb6f..99da2329 100644
--- a/providers/front-logger.js
+++ b/providers/front-logger.js
@@ -7,7 +7,7 @@ function logToString(log) {
}
module.exports = () => {
- ipcRenderer.on("log", (event, log) => {
+ ipcRenderer.on("log", (_event, log) => {
console.log(logToString(log));
});
};