Users of applications generally move around and re-size windows for their liking. When they reopen the same application they expect the window to be in the same place they close it. In fact, I have a manager who get's extremely pissed if he opens an application and it isn't exactly where he left it. In this post I'll show you how to save and restore window state between sessions in Electron.

If you are new to Electron check out my previous posts on Getting Started With Electron in Visual Studio Code.

Basic Flow

The flow of doing this is pretty simple. Before you create the window you get the previous window state from some repository. If the previous state exists you open the window with its bounds. If it does not exist you use default bounds. You then setup an even handler for the close event. On close you save the window state in the repository for the next time you open the application.

Setting Up Storage Repository

The simplest way to store previous state is to do so using a flat file. To abstract this process away create a storage.js node module that will load and save a JSON file to user storage. Here is the storage module I came up with:

var app = require('app');

var fs = require('fs');

var path = require('path');

var data = null;

var dataFilePath = path.join(app.getPath('userData'), 'data.json'); 



function load() {

 if (data !== null) {

 return;

 } 

 

 if (!fs.existsSync(dataFilePath)) {

 data = {};

 return;

 }

 

 data = JSON.parse(fs.readFileSync(dataFilePath, 'utf-8')); 

}



function save() {

 fs.writeFileSync(dataFilePath, JSON.stringify(data)); 

}



exports.set = function (key, value) {

 load();

 data[key] = value; 

 save();

}



exports.get = function (key) { 

 load();

 var value = null;

 if (key in data) {

 value = data[key];

 } 

 return value;

}



exports.unset = function (key) { 

 load();

 if (key in data) {

 delete data[key];

 save();

 } 

}

The app.getPath('userData') gets local storage for user data. In Windows 8.1 (which I am running) it ends up in C:/Users/<username>/AppData/Roaming/<appname>/. In Linux it is supposed to point at ~/.config/<appname> and ~/Library/Application Support/<appname> in OS X.

Saving and Restoring State

To save and restore the window state you'll need to add a bit of code to the main.js file where you create your BrowserWindow instances.

First thing you need to do is set it up so that your main window saves its state when it is closed. To do this, add an event handler to the close event (note: not the closed event). In the event handler, grab the window bounds and whether or not it is maximized and save them as an object to storage under the key lastWindowState:

var storage = require("./libs/storage"); // I put storage.js in libs folder



/* ... after mainWindow is created ... */



 mainWindow.on('close', function () {

  var bounds = mainWindow.getBounds(); 

  storage.set("lastWindowState", {

   x: bounds.x,

   y: bounds.y,

   width: bounds.width,

   height: bounds.height,

   maximized: mainWindow.isMaximized()

  });

 });

The getBounds method will give us most everything we need except whether or not the window was maximized. That can be retrieved with the isMaximized method.

Next, you'll need to add some code at the time the BrowserWindow is created that will read the last window state from storage and construct the new window with that configuration or a default configuration depending on whether or not state has been saved prior:

var lastWindowState = storage.get("lastWindowState");

if (lastWindowState === null) {

 lastWindowState = {

  width: 1024,

  height: 768,

  maximized: false 

 } 

}



mainWindow = new BrowserWindow({

 x: lastWindowState.x,

 y: lastWindowState.y,

 width: lastWindowState.width, 

 height: lastWindowState.height});



if (lastWindowState.maximized) {

 mainWindow.maximize();

}

There you go. You should now be able to move and re-size your Electron window and have that window restored the next time you open your application!