index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. const path = require('path');
  2. const electron = require('electron');
  3. const DEFAULT_WIDTH = 370;
  4. const DEFAULT_HEIGHT = 160;
  5. function getElectronMainExport(id) {
  6. if (electron[id]) {
  7. return electron[id];
  8. }
  9. let remote = electron.remote;
  10. if (!remote) {
  11. try {
  12. remote = require('@electron/remote');
  13. } catch (originalError) {
  14. const error = new Error(
  15. 'Install and set-up package `@electron/remote` to use this module from a renderer processs.\n'
  16. + 'It is preferable to set up message exchanges for this using `ipcMain.handle()` and `ipcRenderer.invoke()`,\n'
  17. + 'avoiding remote IPC overhead costs, and one morepackage dependancy.\n\n'
  18. + 'Original error message:\n\n'
  19. + originalError.message,
  20. );
  21. error.originalError = originalError;
  22. throw error;
  23. }
  24. }
  25. if (remote && remote[id]) {
  26. return remote[id];
  27. }
  28. throw new Error('Unknown electron export: ' + String(id));
  29. }
  30. const BrowserWindow = getElectronMainExport('BrowserWindow');
  31. const ipcMain = getElectronMainExport('ipcMain');
  32. function electronPrompt(options, parentWindow) {
  33. return new Promise((resolve, reject) => {
  34. const id = `${Date.now()}-${Math.random()}`;
  35. const options_ = Object.assign(
  36. {
  37. width: DEFAULT_WIDTH,
  38. height: DEFAULT_HEIGHT,
  39. minWidth: DEFAULT_WIDTH,
  40. minHeight: DEFAULT_HEIGHT,
  41. resizable: false,
  42. title: 'Prompt',
  43. label: 'Please input a value:',
  44. buttonLabels: null,
  45. alwaysOnTop: false,
  46. value: null,
  47. type: 'input',
  48. selectOptions: null,
  49. icon: null,
  50. useHtmlLabel: false,
  51. customStylesheet: null,
  52. menuBarVisible: false,
  53. skipTaskbar: true,
  54. },
  55. options || {},
  56. );
  57. if (options_.type === 'select' && (options_.selectOptions === null || typeof options_.selectOptions !== 'object')) {
  58. reject(new Error('"selectOptions" must be an object'));
  59. return;
  60. }
  61. let promptWindow = new BrowserWindow({
  62. width: options_.width,
  63. height: options_.height,
  64. minWidth: options_.minWidth,
  65. minHeight: options_.minHeight,
  66. resizable: options_.resizable,
  67. minimizable: false,
  68. fullscreenable: false,
  69. maximizable: false,
  70. parent: parentWindow,
  71. skipTaskbar: options_.skipTaskbar,
  72. alwaysOnTop: options_.alwaysOnTop,
  73. useContentSize: options_.resizable,
  74. modal: Boolean(parentWindow),
  75. title: options_.title,
  76. icon: options_.icon || undefined,
  77. webPreferences: {
  78. nodeIntegration: true,
  79. contextIsolation: false,
  80. },
  81. });
  82. promptWindow.setMenu(null);
  83. promptWindow.setMenuBarVisibility(options_.menuBarVisible);
  84. const getOptionsListener = event => {
  85. event.returnValue = JSON.stringify(options_);
  86. };
  87. const cleanup = () => {
  88. ipcMain.removeListener('prompt-get-options:' + id, getOptionsListener);
  89. ipcMain.removeListener('prompt-post-data:' + id, postDataListener);
  90. ipcMain.removeListener('prompt-error:' + id, errorListener);
  91. if (promptWindow) {
  92. promptWindow.close();
  93. promptWindow = null;
  94. }
  95. };
  96. const postDataListener = (event, value) => {
  97. resolve(value);
  98. event.returnValue = null;
  99. cleanup();
  100. };
  101. const unresponsiveListener = () => {
  102. reject(new Error('Window was unresponsive'));
  103. cleanup();
  104. };
  105. const errorListener = (event, message) => {
  106. reject(new Error(message));
  107. event.returnValue = null;
  108. cleanup();
  109. };
  110. ipcMain.on('prompt-get-options:' + id, getOptionsListener);
  111. ipcMain.on('prompt-post-data:' + id, postDataListener);
  112. ipcMain.on('prompt-error:' + id, errorListener);
  113. promptWindow.on('unresponsive', unresponsiveListener);
  114. promptWindow.on('closed', () => {
  115. promptWindow = null;
  116. cleanup();
  117. resolve(null);
  118. });
  119. promptWindow.loadFile(
  120. path.join(__dirname, 'page', 'prompt.html'),
  121. {hash: id},
  122. );
  123. });
  124. }
  125. module.exports = electronPrompt;