mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 15:27:17 +00:00
refactor: Remove use of localStorage for local settings
Change-Type: minor
This commit is contained in:
parent
447efc7096
commit
2a6670a404
@ -16,20 +16,24 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const electron = require('electron')
|
||||
const Bluebird = require('bluebird')
|
||||
const _ = require('lodash')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const os = require('os')
|
||||
const Storage = require('./storage')
|
||||
|
||||
/**
|
||||
* @summary Local storage settings key
|
||||
* @summary Userdata directory path
|
||||
* @description
|
||||
* Defaults to the following:
|
||||
* - `%APPDATA%/etcher` on Windows
|
||||
* - `$XDG_CONFIG_HOME/etcher` or `~/.config/etcher` on Linux
|
||||
* - `~/Library/Application Support/etcher` on macOS
|
||||
* @constant
|
||||
* @type {String}
|
||||
*/
|
||||
const LOCAL_STORAGE_SETTINGS_KEY = 'etcher-settings'
|
||||
const settingsStorage = new Storage(LOCAL_STORAGE_SETTINGS_KEY)
|
||||
const USER_DATA_DIR = electron.remote.app.getPath('userData')
|
||||
|
||||
/**
|
||||
* @summary Local settings filename
|
||||
@ -38,10 +42,19 @@ const settingsStorage = new Storage(LOCAL_STORAGE_SETTINGS_KEY)
|
||||
*/
|
||||
const RCFILE = '.etcher.json'
|
||||
|
||||
/**
|
||||
* @summary Configuration file path
|
||||
* @type {String}
|
||||
* @constant
|
||||
*/
|
||||
const HOME_CONFIG_PATH = process.platform === 'win32'
|
||||
? path.join(USER_DATA_DIR, RCFILE)
|
||||
: path.join(USER_DATA_DIR, 'config.json')
|
||||
|
||||
/**
|
||||
* @summary Read a local .etcherrc file
|
||||
* @function
|
||||
* @public
|
||||
* @private
|
||||
*
|
||||
* @param {String} filename - file path
|
||||
* @fulfil {Object} - settings
|
||||
@ -68,6 +81,33 @@ const readConfigFile = (filename) => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Read a local .etcherrc file
|
||||
* @function
|
||||
* @private
|
||||
*
|
||||
* @param {String} filename - file path
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
* writeConfigFile('.etcherrc', { something: 'good' })
|
||||
* .then(() => {
|
||||
* console.log('data written')
|
||||
* })
|
||||
*/
|
||||
const writeConfigFile = (filename, data) => {
|
||||
return new Bluebird((resolve, reject) => {
|
||||
const contents = JSON.stringify(data, null, 2)
|
||||
fs.writeFile(filename, contents, (error) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Read all local settings
|
||||
* @function
|
||||
@ -82,22 +122,7 @@ const readConfigFile = (filename) => {
|
||||
* });
|
||||
*/
|
||||
exports.readAll = () => {
|
||||
const homeConfigPath = process.platform === 'win32'
|
||||
? path.join(os.userInfo().homedir, RCFILE)
|
||||
: path.join(os.userInfo().homedir, '.config', 'etcher', 'config.json')
|
||||
const workdirConfigPath = path.join(process.cwd(), RCFILE)
|
||||
const settings = {}
|
||||
return Bluebird.try(() => {
|
||||
_.merge(settings, settingsStorage.getAll())
|
||||
}).return(readConfigFile(homeConfigPath))
|
||||
.then((homeConfig) => {
|
||||
_.merge(settings, homeConfig)
|
||||
})
|
||||
.return(readConfigFile(workdirConfigPath))
|
||||
.then((workdirConfig) => {
|
||||
_.merge(settings, workdirConfig)
|
||||
})
|
||||
.return(settings)
|
||||
return readConfigFile(HOME_CONFIG_PATH)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,9 +141,7 @@ exports.readAll = () => {
|
||||
* });
|
||||
*/
|
||||
exports.writeAll = (settings) => {
|
||||
return Bluebird.try(() => {
|
||||
settingsStorage.setAll(settings)
|
||||
})
|
||||
return writeConfigFile(HOME_CONFIG_PATH, settings)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +160,8 @@ exports.writeAll = (settings) => {
|
||||
* });
|
||||
*/
|
||||
exports.clear = () => {
|
||||
// TODO: Unlink config file
|
||||
return Bluebird.try(() => {
|
||||
settingsStorage.clearAll()
|
||||
// settingsStorage.clearAll()
|
||||
})
|
||||
}
|
||||
|
@ -23,58 +23,32 @@
|
||||
const _ = require('lodash')
|
||||
const Bluebird = require('bluebird')
|
||||
const localSettings = require('./local-settings')
|
||||
const store = require('./store')
|
||||
const errors = require('../../../shared/errors')
|
||||
|
||||
/**
|
||||
* @summary Set a settings object
|
||||
* @function
|
||||
* @private
|
||||
*
|
||||
* @description
|
||||
* Use this function with care, given that it will completely
|
||||
* override any existing settings in both the redux store,
|
||||
* and the local user configuration.
|
||||
*
|
||||
* This function is prepared to deal with any local configuration
|
||||
* write issues by rolling back to the previous settings if so.
|
||||
*
|
||||
* @param {Object} settings - settings
|
||||
* @returns {Promise}
|
||||
*
|
||||
* @example
|
||||
* setSettingsObject({ foo: 'bar' }).then(() => {
|
||||
* console.log('Done!');
|
||||
* });
|
||||
*/
|
||||
const setSettingsObject = (settings) => {
|
||||
const currentSettings = exports.getAll()
|
||||
|
||||
return Bluebird.try(() => {
|
||||
store.dispatch({
|
||||
type: store.Actions.SET_SETTINGS,
|
||||
data: settings
|
||||
})
|
||||
}).then(() => {
|
||||
// Revert the application state if writing the data
|
||||
// to the local machine was not successful
|
||||
return localSettings.writeAll(settings).catch((error) => {
|
||||
store.dispatch({
|
||||
type: store.Actions.SET_SETTINGS,
|
||||
data: currentSettings
|
||||
})
|
||||
|
||||
throw error
|
||||
})
|
||||
})
|
||||
}
|
||||
const release = require('../../../shared/release')
|
||||
const packageJSON = require('../../../../package.json')
|
||||
|
||||
/**
|
||||
* @summary Default settings
|
||||
* @constant
|
||||
* @type {Object}
|
||||
*/
|
||||
const DEFAULT_SETTINGS = store.Defaults.get('settings').toJS()
|
||||
const DEFAULT_SETTINGS = {
|
||||
unsafeMode: false,
|
||||
errorReporting: true,
|
||||
unmountOnSuccess: true,
|
||||
validateWriteOnSuccess: true,
|
||||
updatesEnabled: packageJSON.updates.enabled && !_.includes([ 'rpm', 'deb' ], packageJSON.packageType),
|
||||
includeUnstableUpdateChannel: !release.isStableRelease(packageJSON.version),
|
||||
lastSleptUpdateNotifier: null,
|
||||
lastSleptUpdateNotifierVersion: null,
|
||||
desktopNotifications: true
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Settings state
|
||||
* @type {Object}
|
||||
*/
|
||||
const settings = _.assign({}, DEFAULT_SETTINGS)
|
||||
|
||||
/**
|
||||
* @summary Reset settings to their default values
|
||||
@ -89,7 +63,8 @@ const DEFAULT_SETTINGS = store.Defaults.get('settings').toJS()
|
||||
* });
|
||||
*/
|
||||
exports.reset = () => {
|
||||
return setSettingsObject(DEFAULT_SETTINGS)
|
||||
// TODO: Remove default settings from config file (?)
|
||||
return exports.assign(DEFAULT_SETTINGS)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,14 +82,14 @@ exports.reset = () => {
|
||||
* console.log('Done!');
|
||||
* });
|
||||
*/
|
||||
exports.assign = (settings) => {
|
||||
if (_.isNil(settings)) {
|
||||
exports.assign = (data) => {
|
||||
if (_.isNil(data)) {
|
||||
return Bluebird.reject(errors.createError({
|
||||
title: 'Missing settings'
|
||||
}))
|
||||
}
|
||||
|
||||
return setSettingsObject(_.assign(exports.getAll(), settings))
|
||||
return localSettings.writeAll(_.assign(exports.getAll(), data))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,7 +152,7 @@ exports.set = (key, value) => {
|
||||
* const value = settings.get('unmountOnSuccess');
|
||||
*/
|
||||
exports.get = (key) => {
|
||||
return _.get(exports.getAll(), [ key ])
|
||||
return _.cloneDeep(_.get(settings, [ key ]))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,5 +167,5 @@ exports.get = (key) => {
|
||||
* console.log(allSettings.unmountOnSuccess);
|
||||
*/
|
||||
exports.getAll = () => {
|
||||
return store.getState().get('settings').toJS()
|
||||
return _.cloneDeep(settings)
|
||||
}
|
||||
|
@ -23,10 +23,8 @@ const uuidV4 = require('uuid/v4')
|
||||
const constraints = require('../../../shared/drive-constraints')
|
||||
const supportedFormats = require('../../../shared/supported-formats')
|
||||
const errors = require('../../../shared/errors')
|
||||
const release = require('../../../shared/release')
|
||||
const fileExtensions = require('../../../shared/file-extensions')
|
||||
const utils = require('../../../shared/utils')
|
||||
const packageJSON = require('../../../../package.json')
|
||||
|
||||
/**
|
||||
* @summary Verify and throw if any state fields are nil
|
||||
@ -95,17 +93,6 @@ const DEFAULT_STATE = Immutable.fromJS({
|
||||
percentage: 0,
|
||||
speed: 0,
|
||||
totalSpeed: 0
|
||||
},
|
||||
settings: {
|
||||
unsafeMode: false,
|
||||
errorReporting: true,
|
||||
unmountOnSuccess: true,
|
||||
validateWriteOnSuccess: true,
|
||||
updatesEnabled: packageJSON.updates.enabled && !_.includes([ 'rpm', 'deb' ], packageJSON.packageType),
|
||||
includeUnstableUpdateChannel: !release.isStableRelease(packageJSON.version),
|
||||
lastSleptUpdateNotifier: null,
|
||||
lastSleptUpdateNotifierVersion: null,
|
||||
desktopNotifications: true
|
||||
}
|
||||
})
|
||||
|
||||
@ -123,8 +110,7 @@ const ACTIONS = _.fromPairs(_.map([
|
||||
'SELECT_DRIVE',
|
||||
'SELECT_IMAGE',
|
||||
'DESELECT_DRIVE',
|
||||
'DESELECT_IMAGE',
|
||||
'SET_SETTINGS'
|
||||
'DESELECT_IMAGE'
|
||||
], (message) => {
|
||||
return [ message, message ]
|
||||
}))
|
||||
@ -512,34 +498,6 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
||||
return state.deleteIn([ 'selection', 'image' ])
|
||||
}
|
||||
|
||||
case ACTIONS.SET_SETTINGS: {
|
||||
// Type: action.data : SettingsObject
|
||||
|
||||
if (!action.data) {
|
||||
throw errors.createError({
|
||||
title: 'Missing settings'
|
||||
})
|
||||
}
|
||||
|
||||
if (!_.isPlainObject(action.data)) {
|
||||
throw errors.createError({
|
||||
title: `Invalid settings: ${action.data}`
|
||||
})
|
||||
}
|
||||
|
||||
const invalidPair = _.find(_.toPairs(action.data), (pair) => {
|
||||
return _.isObject(_.last(pair))
|
||||
})
|
||||
|
||||
if (!_.isNil(invalidPair)) {
|
||||
throw errors.createError({
|
||||
title: `Invalid setting value: ${_.last(invalidPair)} for ${_.first(invalidPair)}`
|
||||
})
|
||||
}
|
||||
|
||||
return state.setIn([ 'settings' ], Immutable.fromJS(action.data))
|
||||
}
|
||||
|
||||
default: {
|
||||
return state
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user