November 2019 00:51 #electron. You Cannot Submit an Electron 6 (or 7) App to the Apple Store. Allright, as a follow up to the previous chapter in this odyssey I can now state that, apparently, you cannot submit an electron 6 or 7 app to the apple store: The first refusal from apple states. At Identifiers section Add new App ID for macOS platform. Next go to Profiles and create new Provisioning profile for Mac App Store distribution. Download created profile and place to build folder inside your application source folder. Name it as embedded.provisionprofile. Go to App Store Connect and select My Apps. FYI I installed the last 5.x release of Electron, built my app and then signed as per the documentation. The app ran without crashing, and also the app didn't contain the Helper apps (probably obvious!) However, the app window (from an icon in the menu bar) is blank after signing.
Code in this article can be found here: https://github.com/ccnokes/electron-tutorials
Most Electron apps need some sort of way to save user data. This could be user preferences (e.g. show/don’t show notifications) or some kind of application data (e.g. last window size and position). So how do we save user settings in an Electron app? And where do we save them to?
Because we have access to both browser and node.js APIs, we have some options for persisting user data. Let’s go over them and then we’ll look at a practical example.
HTML5 Storage APIs (localStorage and IndexedDB)
If you primarily access your data in the renderer process, this is the simplest solution. You can access HTML5 storage data from the main process via electron-remote, which provides an asynchronous API to a hidden browser window that can execute DOM/renderer specific code. One drawback to this might be the fact that the API you use to get/set your user data in the main (async) will be different from the what is in the renderer (sync). This is a pretty attractive solution, and one I plan to play around with.
Flat file
If we want to access that data easily from both the renderer and main, using the same API, we can use the node.js fs
(file system) module to save data to a JSON file (or any format we want). This approach covers the most common use cases, so we’ll cover how to do this in an example in a moment.
Embedded database
If we have larger data storage needs there are “embedded” databases like neDB (implements the Mongo API) or sqlite that we could use. Note that this could introduce some complexity because sometimes these databases (like sqlite) are native node modules (they use C++), and shipping cross-platform native code, even through NPM, can have some gotchas. Most applications that I’ve seen/heard of don’t have such complicated storage needs, but I’m sure there’s some use cases for it.
Where should I store the data?
Typically data is stored in the user’s “app data” folder.Where this directory is varies by operating system.
- Mac OS:
~/Library/Application Support/<Your App Name (taken from the name property in package.json)>
- Windows:
C:Users<you>AppDataLocal<Your App Name>
- Linux:
~/.config/<Your App Name>
Electron provides app.getPath which returns the right directory, depending on your platform.
Why not store the user data closer to all our app’s source files?
Storing user data in the operating system’s designated location for user’s app data is the idiomatic way for native app’s to persist user data because:
Electron Builder Entitlements
when we auto-update the app, our source files may get moved or delete
changing or adding to an app’s internal files will invalidate the code signature
Let’s persist some data (example)
I think the most common use cases are covered by storing our data as JSON in the user data directory. Let’s see how we could implement a module in our app that could handle saving/loading the size of the window. When we resize the window, we’ll save the new size to a file. When the app starts, we’ll load that file, and pass in the saved size to our BrowserWindow
instance.
Let’s encapsulate the data getting and setting logic in a class called Store. The main things this class needs to do is read/write to a file and get/set values. We’ll also make it so that it can work in either the renderer or main process. When it saves the file, it needs to save the file to the user’s app data directory. We’ll make it so our class takes an options object as the first argument. We’ll pass in the data file name and some defaults in the options.
Ok that’s it. Pretty simple. Now let’s integrate it into our app.
All done. Now let’s start our app up and test it out.
Resizing the window will cause the file to be written. It should look something like:
Our Store class is actually compatible with a community module called electron-config (yep, we implemented the same API), and it’s a great module with more features and test coverage.
Electron Mac App Store Apple
Saving the window’s position and size is a common use case in Electron apps. Another convenient community module that handles this is electron-window-state.
Apple Mac Electron App Store
There you have it!