Create readme.md

refactor and css fix

xo --fix

add inline doc

fix typo
This commit is contained in:
Araxeus
2021-04-06 21:57:16 +03:00
parent 6d44a579a4
commit 980ffb45e9
11 changed files with 306 additions and 183 deletions

View File

@ -110,8 +110,8 @@ function createMainWindow() {
titleBarStyle: useInlineMenu titleBarStyle: useInlineMenu
? "hidden" ? "hidden"
: is.macOS() : is.macOS()
? "hiddenInset" ? "hiddenInset"
: "default", : "default",
autoHideMenuBar: config.get("options.hideMenu"), autoHideMenuBar: config.get("options.hideMenu"),
}); });
if (windowPosition) { if (windowPosition) {
@ -156,7 +156,7 @@ function createMainWindow() {
let createdWindow = false; let createdWindow = false;
app.on("browser-window-created", (event, win) => { app.on("browser-window-created", (event, win) => {
//Ensure listeners aren't registered when creating input dialog //Ensures listeners are registered only once
if (createdWindow) { if (createdWindow) {
return; return;
} }
@ -172,7 +172,7 @@ app.on("browser-window-created", (event, win) => {
frameProcessId, frameProcessId,
frameRoutingId, frameRoutingId,
) => { ) => {
let log = { const log = {
error: "did-fail-load", error: "did-fail-load",
event, event,
errorCode, errorCode,
@ -183,7 +183,7 @@ app.on("browser-window-created", (event, win) => {
frameRoutingId, frameRoutingId,
}; };
if (is.dev()) { if (is.dev()) {
console.log(log); console.log(log.toString());
} }
win.webContents.send("log", log); win.webContents.send("log", log);
win.webContents.loadFile(path.join(__dirname, "error.html")); win.webContents.loadFile(path.join(__dirname, "error.html"));
@ -306,13 +306,11 @@ app.on("ready", () => {
} }
// Optimized for Mac OS X // Optimized for Mac OS X
if (is.macOS()) { if (is.macOS() && !config.get("options.appVisible")) {
if (!config.get("options.appVisible")) { app.dock.hide();
app.dock.hide();
}
} }
var forceQuit = false; let forceQuit = false;
app.on("before-quit", () => { app.on("before-quit", () => {
forceQuit = true; forceQuit = true;
}); });

View File

@ -12,6 +12,7 @@ const pluginEnabledMenu = (win, plugin, label = "", hasSubmenu = false) => ({
label: label || plugin, label: label || plugin,
type: "checkbox", type: "checkbox",
checked: config.plugins.isEnabled(plugin), checked: config.plugins.isEnabled(plugin),
//Submenu check used in in-app-menu
hasSubmenu: hasSubmenu || undefined, hasSubmenu: hasSubmenu || undefined,
click: (item) => { click: (item) => {
if (item.checked) { if (item.checked) {
@ -321,13 +322,13 @@ function setProxy(item, win) {
}, },
type: 'input', type: 'input',
icon: iconPath, 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 //TODO: custom bar on prompt need testing on macOS
if(!is.macOS()) { if(!is.macOS()) {
Object.assign(options, { Object.assign(options, {
frame: false, frame: false,
customScript: path.join(__dirname, "providers", "prompt", "customTitlebar.js"), customScript: path.join(__dirname, "providers", "prompt", "custom-titlebar.js"),
enableRemoteModule: true, enableRemoteModule: true,
height: 200, height: 200,
width: 450, width: 450,
@ -337,7 +338,7 @@ function setProxy(item, win) {
.then((input) => { .then((input) => {
if (input !== null && input !== example) { if (input !== null && input !== example) {
config.set("options.proxy", input); config.set("options.proxy", input);
item.checked = (input === "") ? false : true; item.checked = input !== "";
} else { //user pressed cancel } else { //user pressed cancel
item.checked = !item.checked; //reset checkbox item.checked = !item.checked; //reset checkbox
} }

View File

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

View File

@ -9,8 +9,6 @@ const { injectCSS } = require("../utils");
//check that menu doesn't get created twice //check that menu doesn't get created twice
let calledReadyToShow = false; let calledReadyToShow = false;
//check menu state isn't changed twice
let calledFinishedLoad = false
//tracks menu visibility //tracks menu visibility
let visible = true; let visible = true;
// win hook for fixing menu // win hook for fixing menu
@ -37,6 +35,7 @@ module.exports = (winImport) => {
if (calledReadyToShow) { if (calledReadyToShow) {
return; return;
} }
calledReadyToShow = true; calledReadyToShow = true;
setApplicationMenu(win); setApplicationMenu(win);
@ -53,7 +52,7 @@ module.exports = (winImport) => {
win.webContents.on("did-finish-load", () => { win.webContents.on("did-finish-load", () => {
// fix bug with menu not applying on start when no internet connection available // fix bug with menu not applying on start when no internet connection available
setMenuVisibility(!config.get("options.hideMenu")); setMenuVisibility(!config.get("options.hideMenu"));
}) });
}; };
function switchMenuVisibility() { function switchMenuVisibility() {
@ -81,10 +80,10 @@ function updateTemplate(template) {
for (let item of template) { for (let item of template) {
// Change onClick of checkbox+radio // Change onClick of checkbox+radio
if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) { if ((item.type === "checkbox" || item.type === "radio") && !item.fixed) {
let originalOnclick = item.click; const originalOnclick = item.click;
item.click = (itemClicked) => { item.click = (itemClicked) => {
originalOnclick(itemClicked); originalOnclick(itemClicked);
updateCheckboxesAndRadioButtons(itemClicked, item.type === 'radio', item.hasSubmenu); updateCheckboxesAndRadioButtons(itemClicked, item.type === "radio", item.hasSubmenu);
}; };
item.fixed = true; item.fixed = true;
} }

View File

@ -1,11 +1,15 @@
const { ipcRenderer } = require("electron"); 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 = () => { module.exports = () => {
ipcRenderer.on("log", (event, log) => { ipcRenderer.on("log", (event, log) => {
let string = log || log.toString(); console.log(logToString(log));
if (!string || string === "[object Object]") { });
string = JSON.stringify(log);
}
console.log(string);
})
}; };

View File

@ -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";
};

View File

@ -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';
}

View File

@ -34,7 +34,9 @@ body {
} }
#ok:hover, #ok:hover,
#cancel:hover { #ok:focus,
#cancel:hover,
#cancel:focus {
outline: rgba(60, 0, 0, 0.4) solid 2px; outline: rgba(60, 0, 0, 0.4) solid 2px;
} }

View File

@ -1,17 +1,19 @@
const electron = require('electron'); const electron = require("electron");
const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow; const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;
const ipcMain = electron.ipcMain || electron.remote.ipcMain; const ipcMain = electron.ipcMain || electron.remote.ipcMain;
const url = require('url'); const url = require("url");
const path = require('path'); const path = require("path");
const DEFAULT_WIDTH = 370; const DEFAULT_WIDTH = 370;
const DEFAULT_HEIGHT = 160; const DEFAULT_HEIGHT = 160;
function electronPrompt(options, parentWindow) { function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//id used to ensure unique listeners per window
const id = `${Date.now()}-${Math.random()}`; const id = `${Date.now()}-${Math.random()}`;
//custom options override default
const options_ = Object.assign( const options_ = Object.assign(
{ {
width: DEFAULT_WIDTH, width: DEFAULT_WIDTH,
@ -19,12 +21,12 @@ function electronPrompt(options, parentWindow) {
minWidth: DEFAULT_WIDTH, minWidth: DEFAULT_WIDTH,
minHeight: DEFAULT_HEIGHT, minHeight: DEFAULT_HEIGHT,
resizable: false, resizable: false,
title: 'Prompt', title: "Prompt",
label: 'Please input a value:', label: "Please input a value:",
buttonLabels: null, buttonLabels: null,
alwaysOnTop: false, alwaysOnTop: false,
value: null, value: null,
type: 'input', type: "input",
selectOptions: null, selectOptions: null,
icon: null, icon: null,
useHtmlLabel: false, useHtmlLabel: false,
@ -38,7 +40,7 @@ function electronPrompt(options, parentWindow) {
options || {} 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')); reject(new Error('"selectOptions" must be an object'));
return; return;
} }
@ -50,9 +52,9 @@ function electronPrompt(options, parentWindow) {
minWidth: options_.minWidth, minWidth: options_.minWidth,
minHeight: options_.minHeight, minHeight: options_.minHeight,
resizable: options_.resizable, resizable: options_.resizable,
minimizable: false, minimizable: !options_.skipTaskbar && !parentWindow && !options_.alwaysOnTop,
fullscreenable: false, fullscreenable: options_.resizable,
maximizable: false, maximizable: options_.resizable,
parent: parentWindow, parent: parentWindow,
skipTaskbar: options_.skipTaskbar, skipTaskbar: options_.skipTaskbar,
alwaysOnTop: options_.alwaysOnTop, alwaysOnTop: options_.alwaysOnTop,
@ -70,14 +72,11 @@ function electronPrompt(options, parentWindow) {
promptWindow.setMenu(null); promptWindow.setMenu(null);
promptWindow.setMenuBarVisibility(options_.menuBarVisible); promptWindow.setMenuBarVisibility(options_.menuBarVisible);
const getOptionsListener = event => { //called on exit
event.returnValue = JSON.stringify(options_);
};
const cleanup = () => { const cleanup = () => {
ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener); ipcMain.removeListener("prompt-get-options:" + id, getOptionsListener);
ipcMain.removeListener('prompt-post-data:' + id, postDataListener); ipcMain.removeListener("prompt-post-data:" + id, postDataListener);
ipcMain.removeListener('prompt-error:' + id, errorListener); ipcMain.removeListener("prompt-error:" + id, errorListener);
if (promptWindow) { if (promptWindow) {
promptWindow.close(); 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) => { const postDataListener = (event, value) => {
resolve(value); resolve(value);
event.returnValue = null; event.returnValue = null;
@ -92,34 +97,46 @@ function electronPrompt(options, parentWindow) {
}; };
const unresponsiveListener = () => { const unresponsiveListener = () => {
reject(new Error('Window was unresponsive')); reject(new Error("Window was unresponsive"));
cleanup(); cleanup();
}; };
//get error from front
const errorListener = (event, message) => { const errorListener = (event, message) => {
reject(new Error(message)); reject(new Error(message));
event.returnValue = null; event.returnValue = null;
cleanup(); cleanup();
}; };
ipcMain.on('prompt-get-options:' + id, getOptionsListener); //attach listeners
ipcMain.on('prompt-post-data:' + id, postDataListener); ipcMain.on("prompt-get-options:" + id, getOptionsListener);
ipcMain.on('prompt-error:' + id, errorListener); ipcMain.on("prompt-post-data:" + id, postDataListener);
promptWindow.on('unresponsive', unresponsiveListener); ipcMain.on("prompt-error:" + id, errorListener);
promptWindow.on("unresponsive", unresponsiveListener);
promptWindow.on('closed', () => { promptWindow.on("closed", () => {
promptWindow = null; promptWindow = null;
cleanup(); cleanup();
resolve(null); resolve(null);
}); });
const promptUrl = url.format({ //should never happen
protocol: 'file', promptWindow.webContents.on("did-fail-load", (
slashes: true, event,
pathname: path.join(__dirname, 'page', 'prompt.html'), errorCode,
hash: id 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); promptWindow.loadURL(promptUrl);
}); });
} }

View File

@ -1,126 +1,47 @@
const fs = require('fs'); const fs = require("fs");
const {ipcRenderer} = require('electron'); const {ipcRenderer} = require("electron");
const docReady = require('doc-ready'); const docReady = require("doc-ready");
let promptId = null; let promptId = null;
let promptOptions = 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() { function promptRegister() {
promptId = document.location.hash.replace('#', ''); //get custom session id
promptId = document.location.hash.replace("#", "");
//get options from back
try { try {
promptOptions = JSON.parse(ipcRenderer.sendSync('prompt-get-options:' + promptId)); promptOptions = JSON.parse(ipcRenderer.sendSync("prompt-get-options:" + promptId));
} catch (error) { } catch (error) {
return promptError(error); return promptError(error);
} }
//set label
if (promptOptions.useHtmlLabel) { if (promptOptions.useHtmlLabel) {
document.querySelector('#label').innerHTML = promptOptions.label; document.querySelector("#label").innerHTML = promptOptions.label;
} else { } else {
document.querySelector('#label').textContent = promptOptions.label; document.querySelector("#label").textContent = promptOptions.label;
} }
//set button label
if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) { 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) { 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) { if (promptOptions.customStylesheet) {
try { try {
const customStyleContent = fs.readFileSync(promptOptions.customStylesheet); const customStyleContent = fs.readFileSync(promptOptions.customStylesheet);
if (customStyleContent) { if (customStyleContent) {
const customStyle = document.createElement('style'); const customStyle = document.createElement("style");
customStyle.setAttribute('rel', 'stylesheet'); customStyle.setAttribute("rel", "stylesheet");
customStyle.append(document.createTextNode(customStyleContent)); customStyle.append(document.createTextNode(customStyleContent));
document.head.append(customStyle); document.head.append(customStyle);
} }
@ -129,28 +50,31 @@ function promptRegister() {
} }
} }
document.querySelector('#form').addEventListener('submit', promptSubmit); //add button listeners
document.querySelector('#cancel').addEventListener('click', promptCancel); 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; let dataElement;
if (promptOptions.type === 'input') { if (promptOptions.type === "input") {
dataElement = promptCreateInput(); dataElement = promptCreateInput();
} else if (promptOptions.type === 'select') { } else if (promptOptions.type === "select") {
dataElement = promptCreateSelect(); dataElement = promptCreateSelect();
} else { } else {
return promptError(`Unhandled input type '${promptOptions.type}'`); return promptError(`Unhandled input type '${promptOptions.type}'`);
} }
dataContainerElement.append(dataElement); dataContainerElement.append(dataElement);
dataElement.setAttribute('id', 'data'); dataElement.setAttribute("id", "data");
dataElement.focus(); dataElement.focus();
if (promptOptions.type === 'input') { if (promptOptions.type === "input") {
dataElement.select(); dataElement.select();
} }
//load custom script from options
if (promptOptions.customScript) { if (promptOptions.customScript) {
try { try {
const customScript = require(promptOptions.customScript); const customScript = require(promptOptions.customScript);
@ -161,10 +85,104 @@ function promptRegister() {
} }
} }
window.addEventListener('error', error => { window.addEventListener("error", error => {
if (promptId) { 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); //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;
}

View File

@ -0,0 +1,79 @@
# Prompt Documentation
<p align="center"><img width="482" alt="prompt-preview" src="https://user-images.githubusercontent.com/17620180/111753337-09c0c680-8897-11eb-8ce8-43de29c143bd.png"></p>
## 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}` -> `<input type="text" required>`. 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`
};
```