Persist settings in ${XDG_CONFIG_HOME}/flipper/settings
Summary: Moves the settings state from electron local storage into a json file in the users configured config location. Unless modified by the user, this will usually be `~/.config/flipper/settings.json` Settings will now persist across re-installs, and can now be easily inspected and backed up. Reviewed By: passy Differential Revision: D17712687 fbshipit-source-id: 1e778063e41d0a1a86145817b9797bf0458121da
This commit is contained in:
committed by
Facebook Github Bot
parent
7775e82851
commit
85c0ec0d13
@@ -163,6 +163,6 @@ class SignInSheet extends Component<Props, State> {
|
||||
}
|
||||
|
||||
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
|
||||
({settingsState}) => ({settings: settingsState.settings}),
|
||||
({settingsState}) => ({settings: settingsState}),
|
||||
{updateSettings},
|
||||
)(SignInSheet);
|
||||
|
||||
@@ -27,11 +27,14 @@ import plugins, {
|
||||
Action as PluginsAction,
|
||||
} from './plugins';
|
||||
import settings, {
|
||||
State as SettingsState,
|
||||
Settings as SettingsState,
|
||||
Action as SettingsAction,
|
||||
} from './settings';
|
||||
import user, {State as UserState, Action as UserAction} from './user';
|
||||
|
||||
import JsonFileStorage from '../utils/jsonFileReduxPersistStorage';
|
||||
import os from 'os';
|
||||
import {resolve} from 'path';
|
||||
import xdg from 'xdg-basedir';
|
||||
import {persistReducer, PersistPartial} from 'redux-persist';
|
||||
|
||||
import {Store as ReduxStore, MiddlewareAPI as ReduxMiddlewareAPI} from 'redux';
|
||||
@@ -61,6 +64,14 @@ export type State = {
|
||||
export type Store = ReduxStore<State, Actions>;
|
||||
export type MiddlewareAPI = ReduxMiddlewareAPI<Dispatch<Actions>, State>;
|
||||
|
||||
const settingsStorage = new JsonFileStorage(
|
||||
resolve(
|
||||
...(xdg.config ? [xdg.config] : [os.homedir(), '.config']),
|
||||
'flipper',
|
||||
'settings.json',
|
||||
),
|
||||
);
|
||||
|
||||
export default combineReducers<State, Actions>({
|
||||
application: persistReducer<ApplicationState, Actions>(
|
||||
{
|
||||
@@ -101,7 +112,7 @@ export default combineReducers<State, Actions>({
|
||||
user,
|
||||
),
|
||||
settingsState: persistReducer(
|
||||
{key: 'settings', storage, whitelist: ['settings']},
|
||||
{key: 'settings', storage: settingsStorage},
|
||||
settings,
|
||||
),
|
||||
});
|
||||
|
||||
@@ -11,10 +11,6 @@ export type Settings = {
|
||||
androidHome: string;
|
||||
};
|
||||
|
||||
export type State = {
|
||||
settings: Settings;
|
||||
};
|
||||
|
||||
export type Action =
|
||||
| {type: 'INIT'}
|
||||
| {
|
||||
@@ -22,21 +18,16 @@ export type Action =
|
||||
payload: Settings;
|
||||
};
|
||||
|
||||
const initialState: State = {
|
||||
settings: {
|
||||
androidHome: '/opt/android_sdk',
|
||||
},
|
||||
const initialState: Settings = {
|
||||
androidHome: '/opt/android_sdk',
|
||||
};
|
||||
|
||||
export default function reducer(
|
||||
state: State = initialState,
|
||||
state: Settings = initialState,
|
||||
action: Actions,
|
||||
): State {
|
||||
): Settings {
|
||||
if (action.type === 'UPDATE_SETTINGS') {
|
||||
return {
|
||||
...state,
|
||||
settings: action.payload,
|
||||
};
|
||||
return action.payload;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {promises} from 'fs';
|
||||
import {promises, exists} from 'fs';
|
||||
import path from 'path';
|
||||
import {promisify} from 'util';
|
||||
|
||||
/**
|
||||
* Redux-persist storage engine for storing state in a human readable JSON file.
|
||||
@@ -28,14 +30,12 @@ export default class JsonFileStorage {
|
||||
.then(buffer => buffer.toString())
|
||||
.then(this.deserializeValue)
|
||||
.catch(e => {
|
||||
console.error(
|
||||
console.warn(
|
||||
`Failed to read settings file: "${
|
||||
this.filepath
|
||||
}". ${e}. Replacing file with default settings.`,
|
||||
);
|
||||
return promises
|
||||
.writeFile(this.filepath, JSON.stringify({}))
|
||||
.then(() => ({}));
|
||||
return this.writeContents(JSON.stringify({})).then(() => ({}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export default class JsonFileStorage {
|
||||
setItem(_key: string, value: any, callback?: (_: any) => any): Promise<any> {
|
||||
const originalValue = this.parseFile();
|
||||
const writePromise = originalValue.then(_ =>
|
||||
promises.writeFile(this.filepath, this.serializeValue(value)),
|
||||
this.writeContents(this.serializeValue(value)),
|
||||
);
|
||||
|
||||
return Promise.all([originalValue, writePromise]).then(([o, _]) => {
|
||||
@@ -61,8 +61,7 @@ export default class JsonFileStorage {
|
||||
}
|
||||
|
||||
removeItem(_key: string, callback?: () => any): Promise<void> {
|
||||
return promises
|
||||
.writeFile(this.filepath, JSON.stringify({}))
|
||||
return this.writeContents(JSON.stringify({}))
|
||||
.then(_ => callback && callback())
|
||||
.then(() => {});
|
||||
}
|
||||
@@ -86,4 +85,13 @@ export default class JsonFileStorage {
|
||||
}, {});
|
||||
return JSON.stringify(reconstructedObject);
|
||||
}
|
||||
|
||||
writeContents(content: string): Promise<void> {
|
||||
const dir = path.dirname(this.filepath);
|
||||
return promisify(exists)(dir)
|
||||
.then(dirExists =>
|
||||
dirExists ? Promise.resolve() : promises.mkdir(dir, {recursive: true}),
|
||||
)
|
||||
.then(() => promises.writeFile(this.filepath, content));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user