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 1/5] 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 2/5] 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 3/5] 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 4/5] 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 5/5] 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
+}