Saving files to a local system

In this section, we are going to provide support for saving files to the local filesystem, as well as handling global keyboard shortcuts.

Depending on the platform, you may want to support either Cmd + S for macOS or Ctrl + S for Windows or Linux desktops.

Let's start by switching back to the menu.js file and registering a new global shortcut. The Electron framework is going to handle it regardless of the focused window. It can handle globally registered shortcuts even if no window is present. This is often used when the application provides support for the minimize to tray feature:

  1. Update the menu.js file and import the globalShortcut object from the Electron framework:
      const { globalShortcut } = require('electron');

This object allows you to access shortcut registration utilities. Check out the following code, which shows you how to register a universal shortcut that addresses every platform:

      app.on('ready', () => {
globalShortcut.register('CommandOrControl+S', () => {
console.log('Saving the file');
});
});

Please note that the shortcut is called CommandOrControl+S. This means that, if your application is running on macOS, then Electron is going for listen to Cmd + S clicks. In any other case, it accepts the Ctrl + S click. How convenient!

  1. Now, run or restart the application and, depending on the platform you are using right now, press either Cmd + S or Ctrl + S a few times.
  2. Switch to the Terminal window and check the application's output. You should see the initial message we created earlier, as well as a Saving the file string for each of your clicks:
      Received reply from web page: Page Loaded
Saving the file
Saving the file
Saving the file

This proves that the code is working and our Electron application is able to handle global shortcuts. Next, we need to get the content of the markdown editor somehow and save it to a file.

Work through the following these steps to practice with the event bus:

  1. Node.js is going to send a message to the browser window and notify it that we are about to save a file.
  2. The rendering process should extract the raw text value of the user content and send it back to the main process via another message.
  1. Finally, the Node.js side is going to receive the data, invoke the system dialog to save the file, and write some content to the local disk.
  2. You already know how to send messages. We used the editor-event channel to send toggle-bold commands to the renderer process. Feel free to reuse the same channel to send an extra save command, as shown in the following code:
      app.on('ready', () => {
globalShortcut.register('CommandOrControl+S', () => {
console.log('Saving the file');

const window = BrowserWindow.getFocusedWindow();
window.webContents.send('editor-event', 'save');
});
});

On the renderer process side, we also have an event listener. Now, we need an additional condition handler.

  1. As soon as the save message arrives, we call editor.getValue() to get the actual text inside the markdown editor and send it back using the save channel name:
      if (arg === 'save') {
event.sender.send('save', editor.getValue());
}
  1. Like all the previous implementations, the client-side handler should look as follows:
      const { ipcRenderer } = require('electron');

ipcRenderer.on('editor-event', (event, arg) => {
console.log(arg);
event.sender.send('editor-reply', `Received ${arg}`);

if (arg === 'toggle-bold') {
editor.toggleBold();
}

if (arg === 'save') {
event.sender.send('save', editor.value());
}
});
  1. Now, switch back to the menu.js file and place the listener for the save event that the renderer process should now be raising:
      ipcMain.on('save', (event, arg) => {
console.log(`Saving content of the file`);
console.log(arg);
});

As you can see, this isn't doing much. For the sake of simplicity, it is just putting received data into the Terminal output so that we can verify that the messaging is working as expected.

  1. Before we start testing the data flow, we need to verify that our messaging implementation in menu.js looks as follows:
      app.on('ready', () => {
globalShortcut.register('CommandOrControl+S', () => {
console.log('Saving the file');

const window = BrowserWindow.getFocusedWindow();
window.webContents.send('editor-event', 'save');
});
});

ipcMain.on('save', (event, arg) => {
console.log(`Saving content of the file`);
console.log(arg);
});

ipcMain.on('editor-reply', (event, arg) => {
console.log(`Received reply from web page: ${arg}`);
});

This should help us understand where all the strings in the Terminal window are coming from.

  1. Restart the application and type hello world. Then, click the H button to turn the text into a Heading element:

As soon as you check the Terminal window while the application is running, you should see the following output from all the message handlers we set up earlier:

      Received reply from web page: Page Loaded
Saving the file
Received reply from web page: Received save
Saving content of the file
# hello world

Note that you can also see the entirety of the text content. Try editing the text some more and press Cmd + S or Ctrl + S from time to time. Ensure that the latest text value ends up in the Terminal output.

Now, it's time to save the file to the local disk.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.98.71