Skip to content
Advertisement

Why is electron’s showMessageBoxSync duplicating itself when cancel is clicked?

So the issue is: I open an electron messageBox of type ‘info’ once a button is clicked. It has ‘OK’ and ‘Cancel’ options. If I click ‘OK’, no problem. But when I click ‘Cancel’, then click my button again, another messageBox will open in succession for each time the button has been clicked and ‘Cancel’ was selected each time. Clicking ‘OK’ will end the cycle, so to speak, since the name will be added to the list and ignored after. Though if I click ‘OK’ multiple times when the box is duplicating, the name will be added multiple times, like it’s not working with the most recent version of the names list (which is probably the case).

I’ve been using the contextBridge so the call goes from my main script to preload.js to main.js and back. I don’t think the issue lies in my eventlistener since I only see one call to checkName per button click. Is it my code logic? I’m a bit new to electron so I’m not really sure what’s causing it at this point and haven’t been able to glean anything from the docs/other threads on this behavior.

//index.js
window.onload = function(){
  document.getElementById('myButton').addEventListener('click', checkName);
}

function checkName(){
  var name = document.getElementById('myInput').value;
  window.api.send("sendNames", "");
  window.api.receive("getNames", (names) => {
    //I split names into an array by 'rn' here
    if(!names.includes(name)){
      window.api.confirm("confirmName", "This is the first time this name has been used, would you like 
        to add it now?");
      window.api.receive("getConfirmation", (result) => {
      //I format names as a string here before sending back
      if(result == 0) window.api.update("updateNames", names);
    }
  }
  }
}
//preload.js
contextBridge.exposeInMainWorld(
  "api", {
      send: (channel, data) => {
          let validChannels = ["sendNames"];
          if (validChannels.includes(channel)){
              ipcRenderer.send(channel, data);
          }
      },
      receive: (channel, func) => {
          let validChannels = ["getNames", "getConfirmation"];
          if (validChannels.includes(channel)){
              ipcRenderer.on(channel, (event, ...args) => func(...args));
          }
      },
      update: (channel, data) => {
          let validChannels = ["updateNames"];
          if(validChannels.includes(channel)){
              ipcRenderer.send(channel, data);
          }
      },
      confirm: (channel, data) => {
        let validChannels = ["confirmName"];
        if(validChannels.includes(channel)){
          ipcRenderer.send(channel, data);
        }
      }
  }
);
//main.js
ipcMain.on("sendNames", (event, args) => {
  const fs = require('fs');
  var allUsers = fs.readFileSync('./nameList.txt', 'utf-8');
  mainWindow.webContents.send("getNames", allUsers);
});

ipcMain.on("updateNames", (event, args) => {
  const fs = require('fs');
  fs.writeFileSync('./nameList.txt', args);
}); 

ipcMain.on("confirmName", (event, args) => {
  var options = {
    type: 'info',
    buttons: ['OK', 'Cancel'],
    noLink: true,
    cancelId: 1,
    title: 'Confirm',
    message: args
  };
  mainWindow.webContents.send("getConfirmation", dialog.showMessageBoxSync(mainWindow, options));
});

Advertisement

Answer

Removing all listeners before creating another seems to fix the issue. I would’ve liked to target the specific channel being duplicated, but that didn’t seem to change the behavior at all. I haven’t seen any adverse effect on other listeners’ functionality so I’ll consider this a solution to my problem.

confirm: (channel, data) => {
        ipcRenderer.removeAllListeners();
        let validChannels = ["confirmName"];
        if(validChannels.includes(channel)){
          ipcRenderer.send(channel, data);
        }
      }
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement