Show "Saving..." for 0.5 seconds and show error if it occurred

This commit is contained in:
Yuya Ochiai
2017-02-16 21:55:44 +09:00
parent 949db4ffae
commit 8acd7b99e7
4 changed files with 78 additions and 40 deletions

View File

@@ -14,7 +14,7 @@ function AutoSaveIndicator(props) {
case 'saving': case 'saving':
return 'Saving...'; return 'Saving...';
case 'saved': case 'saved':
return 'Saved!'; return 'Saved';
case 'error': case 'error':
return errorMessage; return errorMessage;
default: default:

View File

@@ -62,17 +62,32 @@ const SettingsPage = React.createClass({
}, },
setSavingState(state) { setSavingState(state) {
if (!this.setSavingStateDone) { if (!this.setSavingStateSaved) {
this.setSavingStateDone = debounce(() => { this.setSavingStateSaved = debounce(() => {
this.setState({savingState: 'done'}); this.saveConfig((err) => {
}, 2000); 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}); this.setState({savingState: state});
if (state === 'saved') { if (state === 'saving') {
this.setSavingStateDone(); this.setSavingStateSaved();
} }
}, },
startSaveConfig() {
this.setSavingState('saving');
},
handleTeamsChange(teams) { handleTeamsChange(teams) {
this.setState({ this.setState({
showAddTeamForm: false, showAddTeamForm: false,
@@ -81,10 +96,10 @@ const SettingsPage = React.createClass({
if (teams.length === 0) { if (teams.length === 0) {
this.setState({showAddTeamForm: true}); this.setState({showAddTeamForm: true});
} }
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
saveConfig() {
this.setSavingState('saving'); saveConfig(callback) {
var config = { var config = {
teams: this.state.teams, teams: this.state.teams,
showTrayIcon: this.state.showTrayIcon, showTrayIcon: this.state.showTrayIcon,
@@ -97,29 +112,39 @@ const SettingsPage = React.createClass({
}, },
showUnreadBadge: this.state.showUnreadBadge 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-menu', config);
ipcRenderer.send('update-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() { handleCancel() {
backToIndex(); backToIndex();
}, },
@@ -127,13 +152,13 @@ const SettingsPage = React.createClass({
this.setState({ this.setState({
disablewebsecurity: this.refs.disablewebsecurity.props.checked disablewebsecurity: this.refs.disablewebsecurity.props.checked
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleChangeHideMenuBar() { handleChangeHideMenuBar() {
this.setState({ this.setState({
hideMenuBar: this.refs.hideMenuBar.props.checked hideMenuBar: this.refs.hideMenuBar.props.checked
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleChangeShowTrayIcon() { handleChangeShowTrayIcon() {
var shouldShowTrayIcon = !this.refs.showTrayIcon.props.checked; var shouldShowTrayIcon = !this.refs.showTrayIcon.props.checked;
@@ -147,19 +172,19 @@ const SettingsPage = React.createClass({
}); });
} }
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleChangeTrayIconTheme() { handleChangeTrayIconTheme() {
this.setState({ this.setState({
trayIconTheme: ReactDOM.findDOMNode(this.refs.trayIconTheme).value trayIconTheme: ReactDOM.findDOMNode(this.refs.trayIconTheme).value
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleChangeAutoStart() { handleChangeAutoStart() {
this.setState({ this.setState({
autostart: !this.refs.autostart.props.checked autostart: !this.refs.autostart.props.checked
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleChangeMinimizeToTray() { handleChangeMinimizeToTray() {
const shouldMinimizeToTray = this.state.showTrayIcon && !this.refs.minimizeToTray.props.checked; const shouldMinimizeToTray = this.state.showTrayIcon && !this.refs.minimizeToTray.props.checked;
@@ -167,7 +192,7 @@ const SettingsPage = React.createClass({
this.setState({ this.setState({
minimizeToTray: shouldMinimizeToTray minimizeToTray: shouldMinimizeToTray
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
toggleShowTeamForm() { toggleShowTeamForm() {
this.setState({ this.setState({
@@ -185,13 +210,13 @@ const SettingsPage = React.createClass({
flashWindow: this.refs.flashWindow.props.checked ? 0 : 2 flashWindow: this.refs.flashWindow.props.checked ? 0 : 2
} }
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
handleShowUnreadBadge() { handleShowUnreadBadge() {
this.setState({ this.setState({
showUnreadBadge: !this.refs.showUnreadBadge.props.checked showUnreadBadge: !this.refs.showUnreadBadge.props.checked
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
updateTeam(index, newData) { updateTeam(index, newData) {
@@ -200,7 +225,7 @@ const SettingsPage = React.createClass({
this.setState({ this.setState({
teams teams
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
addServer(team) { addServer(team) {
@@ -209,7 +234,7 @@ const SettingsPage = React.createClass({
this.setState({ this.setState({
teams teams
}); });
setImmediate(this.saveConfig); setImmediate(this.startSaveConfig);
}, },
render() { render() {
@@ -418,7 +443,10 @@ const SettingsPage = React.createClass({
transitionEnterTimeout={500} transitionEnterTimeout={500}
transitionLeaveTimeout={1000} transitionLeaveTimeout={1000}
> >
{ this.state.savingState === 'done' ? null : <AutoSaveIndicator savingState={this.state.savingState}/> } { this.state.savingState === 'done' ? null : <AutoSaveIndicator
savingState={this.state.savingState}
errorMessage={'Can\'t save your changes. Please try again.'}
/> }
</ReactCSSTransitionGroup> </ReactCSSTransitionGroup>
</div> </div>
<div style={{position: 'relative'}}> <div style={{position: 'relative'}}>

View File

@@ -67,6 +67,14 @@ module.exports = {
return config; 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) { writeFileSync(configFile, config) {
if (config.version !== settingsVersion) { if (config.version !== settingsVersion) {
throw new Error('version ' + config.version + ' is not equal to ' + settingsVersion); throw new Error('version ' + config.version + ' is not equal to ' + settingsVersion);

View File

@@ -100,6 +100,7 @@ describe('browser/settings.html', function desc() {
} }
return true; return true;
}). }).
pause(600).
click('#btnClose'). click('#btnClose').
pause(1000).then(() => { pause(1000).then(() => {
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
@@ -133,6 +134,7 @@ describe('browser/settings.html', function desc() {
} }
return true; return true;
}). }).
pause(600).
click('#btnClose'). click('#btnClose').
pause(1000).then(() => { pause(1000).then(() => {
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8')); const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));