Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

electron dialog box not preventing interaction with page

So this may be a simple fix, but I have been researching and have found no solution. I assumed electron did this by default. In my Electron app I am calling dialog boxes from the renderer process using the remote api. Everything works fine except that, my dialog's don't prevent the user from interacting with the rest of the BrowserWindow. My two functions are as follows

// function for saving a gantt project projects are serialized into a JSON file
// the JSON is then stringified for human readiblity then thru the dialog api is saved to
// users computer
const saveGantt = () => {
  let content = gantt.serialize();
  content = JSON.stringify(content, null, '\t');
  dialog.showSaveDialog(
    {
      defaultPath: `C:\\Users\\${process.env.USERNAME}\\Documents\\`,
      filters: [
        {
          name: 'json',
          extensions: ['json'],
        },
      ],
    },
    (filename) => {
      if (filename === undefined) {
        return;
      }
      fs.writeFile(filename, content, (err) => {
        if (err) {
          dialog.showErrorBox(
            'Save Failed',
            `An error occured saving the file ${err.message}`,
          );
          return;
        }
        dialog.showMessageBox({
          type: 'none',
          title: 'Ganttron',
          message: 'The chart was successfully saved',
          buttons: ['OK'],
        });
      });
    },
  );
};

// function that loads a gantt project uses the dialog api to open a JSON file from
// the users computer then it is parsed to return a JSON object that is then parsed by
// the gantt api
const loadGantt = () => {
  dialog.showMessageBox(
    {
      type: 'none',
      title: 'Ganttron',
      message: 'This will clear the gantt chart and load new data',
      buttons: ['Cancel', 'OK'],
    },
    (response) => {
      if (response === 1) {
        gantt.clearAll();
        dialog.showOpenDialog(
          {
            defaultPath: `C:\\Users\\${process.env.USERNAME}\\Documents`,
            filters: [
              {
                name: 'json',
                extensions: ['json'],
              },
            ],
          },
          (fileName) => {
            if (fileName === undefined) {
              return;
            }
            fs.readFile(fileName[0], 'utf-8', (err, data) => {
              quickSaveFileName = fileName[0].toString();
              if (err) {
                dialog.showErrorBox(
                  'Load Failed',
                  `Cannot read file ${err.message}`,
                );
              }
              const loadedData = JSON.parse(data);
              gantt.parse(loadedData);
            });
          },
        );
      }
    },
  );
};

I am passing callbacks with both my functions. I know if you don't pass callbacks it will block the process but not prevent user interacting outside the dialog box. Am I missing something simple, or does this have to be hacked into electron?

like image 477
kemotoe Avatar asked Sep 20 '17 16:09

kemotoe


1 Answers

So for anybody that comes to the question. I figured it out. I used the remote api function getCurrentWindow() that returns a BrowserWindow instance from the main thread. You can use this to then put it in the first argument when initializing the dialog box. As so

import electron, { remote } from 'electron';

const { dialog } = electron.remote;

const win = remote.getCurrentWindow();

// function for saving a gantt project projects are serialized into a JSON file
// the JSON is then stringified for human readiblity then thru the dialog api is saved to
// users computer
const saveGantt = () => {
  let content = gantt.serialize();
  content = JSON.stringify(content, null, '\t');
  dialog.showSaveDialog(
    win,      // added the browserwindow instance here as the first argument
    {
      defaultPath: `C:\\Users\\${process.env.USERNAME}\\Documents\\`,
      filters: [
        {
          name: 'json',
          extensions: ['json'],
        },
      ],
    },
    (filename) => {
      if (filename === undefined) {
        return;
      }
      fs.writeFile(filename, content, (err) => {
        if (err) {
          dialog.showErrorBox(
            win,
            'Save Failed',
            `An error occured saving the file ${err.message}`,
          );
          return;
        }
        dialog.showMessageBox(
          win,
          {
            type: 'none',
            title: 'Ganttron',
            message: 'The chart was successfully saved',
            buttons: ['OK'],
          },
        );
      });
    },
  );
};

// function that loads a gantt project uses the dialog api to open a JSON file from
// the users computer then it is parsed to return a JSON object that is then parsed by
// the gantt api
const loadGantt = () => {
  dialog.showMessageBox(
    win,         // added the browserwindow instance here as the first argument
    {
      type: 'info',
      title: 'Ganttron',
      message: 'This will clear the gantt chart and load new data',
      buttons: ['Cancel', 'OK'],
    },
    (response) => {
      if (response === 1) {
        gantt.clearAll();
        dialog.showOpenDialog(
          win,
          {
            defaultPath: `C:\\Users\\${process.env.USERNAME}\\Documents`,
            filters: [
              {
                name: 'json',
                extensions: ['json'],
              },
            ],
          },
          (fileName) => {
            if (fileName === undefined) {
              return;
            }
            fs.readFile(fileName[0], 'utf-8', (err, data) => {
              quickSaveFileName = fileName[0].toString();
              if (err) {
                dialog.showErrorBox(
                  win,
                  'Load Failed',
                  `Cannot read file ${err.message}`,
                );
              }
              const loadedData = JSON.parse(data);
              gantt.parse(loadedData);
            });
          },
        );
      }
    },
  );
};

It will prevent interaction with the current window until the dialog box is closed.

like image 120
kemotoe Avatar answered Nov 15 '22 05:11

kemotoe