diff --git a/clients/desktop/app/package-lock.json b/clients/desktop/app/package-lock.json index d671fe322..cb0aeca7a 100644 --- a/clients/desktop/app/package-lock.json +++ b/clients/desktop/app/package-lock.json @@ -3172,6 +3172,14 @@ "repeating": "2.0.1" } }, + "dev": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/dev/-/dev-0.1.3.tgz", + "integrity": "sha1-if3AhwXg5+rvktAS4mdR5NdEMio=", + "requires": { + "inotify": "1.4.2" + } + }, "diffie-hellman": { "version": "5.0.3", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -3182,6 +3190,14 @@ "randombytes": "2.0.6" } }, + "doc-ready": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/doc-ready/-/doc-ready-1.0.4.tgz", + "integrity": "sha1-N/U5GWnP+ZQwP9/vLl1QNX+BZNM=", + "requires": { + "eventie": "1.0.6" + } + }, "dom-walk": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", @@ -3953,6 +3969,11 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" }, + "eventie": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/eventie/-/eventie-1.0.6.tgz", + "integrity": "sha1-1P/IsMK15JPCqhsiy+kY067nRDc=" + }, "events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", @@ -5467,6 +5488,15 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inotify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/inotify/-/inotify-1.4.2.tgz", + "integrity": "sha512-+dq8cO+Um/EiGujOilVGw1AclDq9V4B23z4I+PpytUlgIrWfOG/KxW4k7pRZwHHSoqUzlScCWYuQS8Wa+hYcXg==", + "requires": { + "bindings": "1.3.0", + "nan": "2.10.0" + } + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", diff --git a/clients/desktop/app/package.json b/clients/desktop/app/package.json index 778764685..db67ed345 100644 --- a/clients/desktop/app/package.json +++ b/clients/desktop/app/package.json @@ -24,7 +24,8 @@ "commander": "^2.19.0", "crypto": "^1.0.1", "debounce": "^1.2.0", - "migrate": "^1.6.1", + "dev": "^0.1.3", + "doc-ready": "^1.0.4", "electron-updater": "^3.2.3", "express": "^4.16.4", "hyperbridge-funding-protocol": "^1.0.13", @@ -33,6 +34,7 @@ "hyperbridge-token": "^1.0.12", "json-beautify": "^1.0.1", "lokijs": "^1.5.5", + "migrate": "^1.6.1", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "rimraf": "^2.5.2", diff --git a/clients/desktop/app/src/main/index.js b/clients/desktop/app/src/main/index.js index 22fcd5492..8301f7604 100644 --- a/clients/desktop/app/src/main/index.js +++ b/clients/desktop/app/src/main/index.js @@ -8,7 +8,7 @@ import * as PeerService from '../framework/peer-service' import * as Wallet from '../framework/wallet' import * as Windows from './windows' import * as Updater from './updater' - +import electronPrompt from './windows/prompt/main.js' const config = require('../config') @@ -181,6 +181,21 @@ export const initApp = () => { callback({ cancel: false }) } }) + + // Test for the electron prompt + electronPrompt({ + title: 'TEST PROMPT', + label: 'TEST INPUT', + value: 'TEST', + inputAttr: { + type: 'text' + }, + type: 'input' + }, Windows.main).then(r => { + console.log('Input is ', r); + }).catch(console.error); + + DB.init() Windows.main.init(deeplinkUri, !config.IS_PRODUCTION, argv.tools) diff --git a/clients/desktop/app/src/main/windows/index.js b/clients/desktop/app/src/main/windows/index.js index 5ea37a744..b03913461 100644 --- a/clients/desktop/app/src/main/windows/index.js +++ b/clients/desktop/app/src/main/windows/index.js @@ -1,2 +1,2 @@ -export const main = require('./main') \ No newline at end of file +export const main = require('./main') diff --git a/clients/desktop/app/src/main/windows/prompt.js b/clients/desktop/app/src/main/windows/prompt.js new file mode 100644 index 000000000..d887f8fc6 --- /dev/null +++ b/clients/desktop/app/src/main/windows/prompt.js @@ -0,0 +1,98 @@ +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'); + +function electronPrompt(options, parentWindow) { + return new Promise((resolve, reject) => { + const id = `${new Date().getTime()}-${Math.random()}`; + + const opts = Object.assign( + { + width: 370, + height: 130, + resizable: false, + title: 'Prompt', + label: 'Please input a value:', + alwaysOnTop: false, + value: null, + type: 'input', + selectOptions: null, + icon: null + }, + options || {} + ); + + if (opts.type === 'select' && (opts.selectOptions === null || typeof opts.selectOptions !== 'object')) { + return reject(new Error('"selectOptions" must be an object')); + } + + let promptWindow = new BrowserWindow({ + width: opts.width, + height: opts.height, + resizable: opts.resizable, + parent: parentWindow, + skipTaskbar: true, + alwaysOnTop: opts.alwaysOnTop, + useContentSize: true, + modal: Boolean(parentWindow), + title: opts.title, + icon: opts.icon + }); + + promptWindow.setMenu(null); + + const getOptionsListener = event => { + event.returnValue = JSON.stringify(opts); + }; + + const cleanup = () => { + 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', () => { + ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener); + ipcMain.removeListener('prompt-post-data:' + id, postDataListener); + ipcMain.removeListener('prompt-error:' + id, postDataListener); + resolve(null); + }); + + const promptUrl = url.format({ + protocol: 'file', + slashes: true, + pathname: path.join(__dirname, 'prompt/main.html'), + hash: id + }); + + promptWindow.loadURL(promptUrl); + }); +} + +module.exports = electronPrompt; diff --git a/clients/desktop/app/src/main/windows/prompt/main.css b/clients/desktop/app/src/main/windows/prompt/main.css new file mode 100644 index 000000000..6abe671fe --- /dev/null +++ b/clients/desktop/app/src/main/windows/prompt/main.css @@ -0,0 +1,71 @@ +body { + font-family: "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%; +} + +#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 { + 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/clients/desktop/app/src/main/windows/prompt/main.html b/clients/desktop/app/src/main/windows/prompt/main.html new file mode 100644 index 000000000..efe85811f --- /dev/null +++ b/clients/desktop/app/src/main/windows/prompt/main.html @@ -0,0 +1,19 @@ + + +
+ + + +