Electron Adventures: Episode 86: Remembering User Preferences
Tags: javascript, electron, svelte
Published: 2021-11-03 18:59:13

This is something I probably should have done much earlier in the series, but better late than never.

When user starts the app, it will place the window is some default position, and give it some deafult size, and that's fine. The user can then resize it and move it to whichever monitor and location they want.

The problem is that when the app quits, we never remember that.

Well, let's implement a simple way to remember window position. We'll use `electron-settings` to save our app settings in some JSON file in OS-appropriate place in the filesystem.

### `index.js`

```javascript
let { app, BrowserWindow } = require("electron")
let settings = require("electron-settings")

let windowState = settings.getSync("windowState") || {width: 800, height: 600}

function createWindow() {
  let win = new BrowserWindow({
    x: windowState.x,
    y: windowState.y,
    width: windowState.width,
    height: windowState.height,
    webPreferences: {
      preload: `${__dirname}/preload.js`,
    },
  })

  function saveSettings() {
    windowState = win.getBounds()
    console.log("SAVING", windowState)
    settings.setSync("windowState", windowState)
  }

  win.on("resize", saveSettings)
  win.on("move", saveSettings)
  win.on("close", saveSettings)

  win.loadURL("http://localhost:5000/")
}

app.on("ready", createWindow)

app.on("window-all-closed", () => {
  app.quit()
})
```

So a few things to unpack here.

First, `windowState` is the variable storing our window state - if we don't have any we initialize it to `{width: 800, height: 600}`. Every time this variable changes we save it to JSON-backed `settings` too. And when the app restarts, we load it from that JSON.

When we create a new window, we use data from `windowState`. And finally we attach a few event handlers to update the `windowState` variable when the window is resized or moved.

### Saved JSON

Location of the JSON file is based on name of the app, which is based on `package.json`. I put `"name": "episode-86-remembering-user-preferences"` in `package.json`, and on OSX that means the settings will go to `~/Library/Application\ Support/episode-86-remembering-user-preferences/settings.json` and will look something like this:

```json
{"windowState":{"x":1520,"y":780,"width":707,"height":517}}
```

### Limitations

This solution is good enough for single screen use, unfortunately it doesn't handle a few more complex issues:

* what about maximized / fullscreen / minimized states - this part is OS specific, and we'd unfortunately need to do testing on every OS (and there were some Electron bugs related to such states). I'd say that generally we should not be remembering such special states, and just open the last "normal" window state, but it might vary by app.
* if user has multiple screens, which screen is the window on
* what happens if number of screens changes
* what happens if position is no longer possible (because user is on a different screen, and app would be out of the screen)
* what if the app has multiple windows

Fortunately packages that manage this for us already exist like [`electron-window-state`](https://www.npmjs.com/package/electron-window-state), and hopefully they considered all such issues.

### Results

Here's the results, remembering weird resizing I did:

![Episode 86 Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7zv7hf0cokkb1234ecjo.png)

In the next episode, we'll create a simple game board for our game.

As usual, [all the code for the episode is here](https://github.com/taw/electron-adventures/tree/master/episode-86-remembering-user-preferences).