From 8acd7b99e7fc82625d26d56bc3ca1d99ac31a3f1 Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Thu, 16 Feb 2017 21:55:44 +0900 Subject: [PATCH] Show "Saving..." for 0.5 seconds and show error if it occurred --- src/browser/components/AutoSaveIndicator.jsx | 2 +- src/browser/components/SettingsPage.jsx | 106 ++++++++++++------- src/common/settings.js | 8 ++ test/specs/browser/settings_test.js | 2 + 4 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/browser/components/AutoSaveIndicator.jsx b/src/browser/components/AutoSaveIndicator.jsx index abcc8010..7888d953 100644 --- a/src/browser/components/AutoSaveIndicator.jsx +++ b/src/browser/components/AutoSaveIndicator.jsx @@ -14,7 +14,7 @@ function AutoSaveIndicator(props) { case 'saving': return 'Saving...'; case 'saved': - return 'Saved!'; + return 'Saved'; case 'error': return errorMessage; default: diff --git a/src/browser/components/SettingsPage.jsx b/src/browser/components/SettingsPage.jsx index 63cdd6c6..3331865c 100644 --- a/src/browser/components/SettingsPage.jsx +++ b/src/browser/components/SettingsPage.jsx @@ -62,17 +62,32 @@ const SettingsPage = React.createClass({ }, setSavingState(state) { - if (!this.setSavingStateDone) { - this.setSavingStateDone = debounce(() => { - this.setState({savingState: 'done'}); - }, 2000); + if (!this.setSavingStateSaved) { + this.setSavingStateSaved = debounce(() => { + this.saveConfig((err) => { + if (err) { + this.setState({savingState: 'error'}); + } else { + this.setState({savingState: 'saved'}); + } + this.setSavingStateDoneTimer = setTimeout(this.setState.bind(this, {savingState: 'done'}), 2000); + }); + }, 500); + } + if (this.setSavingStateDoneTimer) { + clearTimeout(this.setSavingStateDoneTimer); + this.setSavingStateDoneTimer = null; } this.setState({savingState: state}); - if (state === 'saved') { - this.setSavingStateDone(); + if (state === 'saving') { + this.setSavingStateSaved(); } }, + startSaveConfig() { + this.setSavingState('saving'); + }, + handleTeamsChange(teams) { this.setState({ showAddTeamForm: false, @@ -81,10 +96,10 @@ const SettingsPage = React.createClass({ if (teams.length === 0) { this.setState({showAddTeamForm: true}); } - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, - saveConfig() { - this.setSavingState('saving'); + + saveConfig(callback) { var config = { teams: this.state.teams, showTrayIcon: this.state.showTrayIcon, @@ -97,29 +112,39 @@ const SettingsPage = React.createClass({ }, showUnreadBadge: this.state.showUnreadBadge }; - settings.writeFileSync(this.props.configFile, config); - if (process.platform === 'win32' || process.platform === 'linux') { - var autostart = this.state.autostart; - appLauncher.isEnabled().then((enabled) => { - if (enabled && !autostart) { - appLauncher.disable().then(() => { - this.setSavingState('saved'); - }); - } else if (!enabled && autostart) { - appLauncher.enable().then(() => { - this.setSavingState('saved'); - }); - } else { - this.setSavingState('saved'); - } - }); - } else { - this.setSavingState('saved'); - } ipcRenderer.send('update-menu', config); ipcRenderer.send('update-config'); + settings.writeFile(this.props.configFile, config, (err) => { + if (err) { + callback(err); + return; + } + if (process.platform === 'win32' || process.platform === 'linux') { + const autostart = this.state.autostart; + this.saveAutoStart(autostart, callback); + } else { + callback(); + } + }); }, + + saveAutoStart(autostart, callback) { + appLauncher.isEnabled().then((enabled) => { + if (enabled && !autostart) { + appLauncher.disable().then(() => { + callback(); + }).catch(callback); + } else if (!enabled && autostart) { + appLauncher.enable().then(() => { + callback(); + }).catch(callback); + } else { + callback(); + } + }).catch(callback); + }, + handleCancel() { backToIndex(); }, @@ -127,13 +152,13 @@ const SettingsPage = React.createClass({ this.setState({ disablewebsecurity: this.refs.disablewebsecurity.props.checked }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleChangeHideMenuBar() { this.setState({ hideMenuBar: this.refs.hideMenuBar.props.checked }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleChangeShowTrayIcon() { var shouldShowTrayIcon = !this.refs.showTrayIcon.props.checked; @@ -147,19 +172,19 @@ const SettingsPage = React.createClass({ }); } - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleChangeTrayIconTheme() { this.setState({ trayIconTheme: ReactDOM.findDOMNode(this.refs.trayIconTheme).value }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleChangeAutoStart() { this.setState({ autostart: !this.refs.autostart.props.checked }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleChangeMinimizeToTray() { const shouldMinimizeToTray = this.state.showTrayIcon && !this.refs.minimizeToTray.props.checked; @@ -167,7 +192,7 @@ const SettingsPage = React.createClass({ this.setState({ minimizeToTray: shouldMinimizeToTray }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, toggleShowTeamForm() { this.setState({ @@ -185,13 +210,13 @@ const SettingsPage = React.createClass({ flashWindow: this.refs.flashWindow.props.checked ? 0 : 2 } }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, handleShowUnreadBadge() { this.setState({ showUnreadBadge: !this.refs.showUnreadBadge.props.checked }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, updateTeam(index, newData) { @@ -200,7 +225,7 @@ const SettingsPage = React.createClass({ this.setState({ teams }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, addServer(team) { @@ -209,7 +234,7 @@ const SettingsPage = React.createClass({ this.setState({ teams }); - setImmediate(this.saveConfig); + setImmediate(this.startSaveConfig); }, render() { @@ -418,7 +443,10 @@ const SettingsPage = React.createClass({ transitionEnterTimeout={500} transitionLeaveTimeout={1000} > - { this.state.savingState === 'done' ? null : } + { this.state.savingState === 'done' ? null : }
diff --git a/src/common/settings.js b/src/common/settings.js index cde9cc8c..e432c3ed 100644 --- a/src/common/settings.js +++ b/src/common/settings.js @@ -67,6 +67,14 @@ module.exports = { return config; }, + writeFile(configFile, config, callback) { + if (config.version !== settingsVersion) { + throw new Error('version ' + config.version + ' is not equal to ' + settingsVersion); + } + var data = JSON.stringify(config, null, ' '); + fs.writeFile(configFile, data, 'utf8', callback); + }, + writeFileSync(configFile, config) { if (config.version !== settingsVersion) { throw new Error('version ' + config.version + ' is not equal to ' + settingsVersion); diff --git a/test/specs/browser/settings_test.js b/test/specs/browser/settings_test.js index c8ea1804..19953ec6 100644 --- a/test/specs/browser/settings_test.js +++ b/test/specs/browser/settings_test.js @@ -100,6 +100,7 @@ describe('browser/settings.html', function desc() { } return true; }). + pause(600). click('#btnClose'). pause(1000).then(() => { const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); @@ -133,6 +134,7 @@ describe('browser/settings.html', function desc() { } return true; }). + pause(600). click('#btnClose'). pause(1000).then(() => { const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));