2016-07-19 04:01:31 +00:00
|
|
|
import React, {Component, PropTypes} from 'react';
|
|
|
|
import {connect} from 'react-redux'
|
|
|
|
import {bindActionCreators} from 'redux';
|
2016-07-07 20:10:55 +00:00
|
|
|
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs'
|
2016-07-16 02:06:10 +00:00
|
|
|
import {shell} from 'electron';
|
2016-05-07 17:29:24 +00:00
|
|
|
|
2016-07-19 19:13:51 +00:00
|
|
|
import Input from './base/Input';
|
2016-07-16 02:06:10 +00:00
|
|
|
import Link from './base/Link';
|
|
|
|
import Modal from './base/Modal';
|
|
|
|
import ModalBody from './base/ModalBody';
|
|
|
|
import ModalHeader from './base/ModalHeader';
|
|
|
|
import ModalFooter from './base/ModalFooter';
|
|
|
|
import ModalComponent from './lib/ModalComponent';
|
2016-07-19 04:01:31 +00:00
|
|
|
import * as GlobalActions from '../redux/modules/global';
|
2016-07-19 19:13:51 +00:00
|
|
|
import * as db from '../database';
|
2016-07-16 02:06:10 +00:00
|
|
|
import {MASHAPE_URL} from '../lib/constants';
|
|
|
|
import {getVersion} from '../lib/appInfo';
|
2016-05-07 17:29:24 +00:00
|
|
|
|
2016-07-19 04:01:31 +00:00
|
|
|
|
|
|
|
class SettingsTabs extends Component {
|
|
|
|
_importFile () {
|
|
|
|
const workspace = this._getActiveWorkspace(this.props);
|
|
|
|
this.props.actions.global.importFile(workspace);
|
|
|
|
}
|
|
|
|
|
|
|
|
_exportFile () {
|
|
|
|
this.props.actions.global.exportFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
_getActiveWorkspace (props) {
|
|
|
|
// TODO: Factor this out into a selector
|
|
|
|
|
|
|
|
const {entities, workspaces} = props || this.props;
|
|
|
|
let workspace = entities.workspaces[workspaces.activeId];
|
|
|
|
if (!workspace) {
|
|
|
|
workspace = entities.workspaces[Object.keys(entities.workspaces)[0]];
|
|
|
|
}
|
|
|
|
|
|
|
|
return workspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
2016-07-21 16:33:35 +00:00
|
|
|
const {entities, selectedIndex} = this.props;
|
2016-07-19 19:13:51 +00:00
|
|
|
const settings = entities.settings[Object.keys(entities.settings)[0]];
|
|
|
|
|
2016-07-19 04:01:31 +00:00
|
|
|
return (
|
2016-07-21 16:33:35 +00:00
|
|
|
<Tabs selectedIndex={selectedIndex >= 0 ? selectedIndex : 0}>
|
2016-07-19 04:01:31 +00:00
|
|
|
<TabList>
|
|
|
|
<Tab>
|
|
|
|
<button>General</button>
|
|
|
|
</Tab>
|
|
|
|
<Tab>
|
|
|
|
<button>Import/Export</button>
|
|
|
|
</Tab>
|
|
|
|
<Tab>
|
|
|
|
<button>Hotkeys</button>
|
|
|
|
</Tab>
|
|
|
|
<Tab>
|
2016-07-19 22:28:29 +00:00
|
|
|
<button>About</button>
|
2016-07-19 04:01:31 +00:00
|
|
|
</Tab>
|
|
|
|
</TabList>
|
|
|
|
<TabPanel className="pad">
|
|
|
|
<div>
|
2016-07-19 22:28:29 +00:00
|
|
|
<h2 className="txt-md">
|
|
|
|
<label className="label--small">General Settings</label>
|
|
|
|
</h2>
|
|
|
|
<div>
|
|
|
|
<Input
|
|
|
|
id="setting-show-passwords"
|
|
|
|
type="checkbox"
|
|
|
|
value={settings.showPasswords}
|
|
|
|
onChange={showPasswords => db.settingsUpdate(settings, {showPasswords})}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<label htmlFor="setting-show-passwords">
|
|
|
|
Show passwords in plain-text
|
|
|
|
</label>
|
|
|
|
</div>
|
2016-07-19 19:13:51 +00:00
|
|
|
|
2016-07-19 22:28:29 +00:00
|
|
|
<div className="pad-top">
|
|
|
|
<Input
|
|
|
|
id="setting-follow-redirects"
|
|
|
|
type="checkbox"
|
|
|
|
value={settings.followRedirects}
|
|
|
|
onChange={followRedirects => db.settingsUpdate(settings, {followRedirects})}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<label htmlFor="setting-follow-redirects">
|
|
|
|
Follow redirects automatically
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{/*<div className="pad-top">*/}
|
|
|
|
{/*<Input*/}
|
|
|
|
{/*id="setting-bulk-header-edit"*/}
|
|
|
|
{/*type="checkbox"*/}
|
|
|
|
{/*value={settings.useBulkHeaderEditor}*/}
|
|
|
|
{/*onChange={useBulkHeaderEditor => db.settingsUpdate(settings, {useBulkHeaderEditor})}*/}
|
|
|
|
{/*/>*/}
|
|
|
|
{/* */}
|
|
|
|
{/*<label htmlFor="setting-bulk-header-edit">*/}
|
|
|
|
{/*Use bulk header editor by default*/}
|
|
|
|
{/*</label>*/}
|
|
|
|
{/*</div>*/}
|
|
|
|
|
|
|
|
{/*<div className="pad-top">*/}
|
|
|
|
{/*<input id="setting-follow-redirects" type="checkbox"/> */}
|
|
|
|
{/*<label htmlFor="setting-follow-redirects">*/}
|
|
|
|
{/*Follow Redirects*/}
|
|
|
|
{/*</label>*/}
|
|
|
|
{/*</div>*/}
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<label htmlFor="setting-request-timeout" className="pad-top">
|
|
|
|
Request Timeout (ms) (-1 for no timeout)
|
|
|
|
</label>
|
|
|
|
<div className="form-control form-control--outlined no-margin">
|
|
|
|
<Input
|
|
|
|
id="setting-request-timeout"
|
|
|
|
type="number"
|
|
|
|
min={-1}
|
|
|
|
value={settings.timeout}
|
|
|
|
onChange={timeout => db.settingsUpdate(settings, {timeout})}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2016-07-19 04:01:31 +00:00
|
|
|
</div>
|
2016-07-19 19:13:51 +00:00
|
|
|
|
2016-07-19 22:28:29 +00:00
|
|
|
<div className="pad-top">
|
|
|
|
<br/>
|
|
|
|
<label className="label--small">Code Editor Settings</label>
|
2016-07-19 19:13:51 +00:00
|
|
|
|
2016-07-19 22:28:29 +00:00
|
|
|
<div className="pad-top">
|
2016-07-19 19:13:51 +00:00
|
|
|
<Input
|
2016-07-19 22:28:29 +00:00
|
|
|
id="setting-editor-line-wrapping"
|
|
|
|
type="checkbox"
|
|
|
|
value={settings.editorLineWrapping}
|
|
|
|
onChange={editorLineWrapping => db.settingsUpdate(settings, {editorLineWrapping})}
|
2016-07-19 19:13:51 +00:00
|
|
|
/>
|
2016-07-19 22:28:29 +00:00
|
|
|
|
|
|
|
<label htmlFor="setting-editor-line-wrapping">
|
|
|
|
Wrap Long Lines
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<label htmlFor="setting-editor-font-size" className="pad-top">
|
|
|
|
Font Size (px)
|
|
|
|
</label>
|
|
|
|
<div className="form-control form-control--outlined no-margin">
|
|
|
|
<Input
|
|
|
|
id="setting-editor-font-size"
|
|
|
|
type="number"
|
|
|
|
min={8}
|
|
|
|
max={20}
|
|
|
|
value={settings.editorFontSize}
|
|
|
|
onChange={editorFontSize => db.settingsUpdate(settings, {editorFontSize})}
|
|
|
|
/>
|
|
|
|
</div>
|
2016-07-19 04:01:31 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</TabPanel>
|
|
|
|
<TabPanel className="pad">
|
|
|
|
<p>
|
|
|
|
Import or export your data, so you can share it or back it up.
|
|
|
|
</p>
|
|
|
|
<p>
|
2016-07-19 19:13:51 +00:00
|
|
|
<button className="btn btn--super-compact btn--outlined"
|
|
|
|
onClick={e => this._importFile()}>
|
2016-07-19 04:01:31 +00:00
|
|
|
Import
|
|
|
|
</button>
|
|
|
|
{" "}
|
2016-07-19 19:13:51 +00:00
|
|
|
<button className="btn btn--super-compact btn--outlined"
|
|
|
|
onClick={e => this._exportFile()}>
|
2016-07-19 04:01:31 +00:00
|
|
|
Export
|
|
|
|
</button>
|
|
|
|
</p>
|
|
|
|
</TabPanel>
|
|
|
|
<TabPanel className="pad">
|
|
|
|
Keyboard
|
|
|
|
</TabPanel>
|
|
|
|
<TabPanel className="pad">
|
2016-07-21 22:04:21 +00:00
|
|
|
<h1>Why hello there!</h1>
|
2016-07-19 04:01:31 +00:00
|
|
|
<p>
|
|
|
|
<Link href="http://insomnia.rest">Insomnia</Link> is made with love by me,
|
|
|
|
<Link href="http://schier.co">Gregory Schier</Link>.
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
You can help me out by sending your feedback to
|
|
|
|
<Link href="mailto:greg@schier.co">greg@schier.co</Link> or tweet
|
|
|
|
<Link href="https://twitter.com/GetInsomnia">@GetInsomnia</Link>.
|
|
|
|
</p>
|
|
|
|
<p>Thanks!</p>
|
|
|
|
<br/>
|
|
|
|
<p>~Gregory</p>
|
|
|
|
</TabPanel>
|
|
|
|
</Tabs>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SettingsTabs.propTypes = {
|
|
|
|
workspaces: PropTypes.shape({
|
|
|
|
activeId: PropTypes.string
|
|
|
|
}),
|
|
|
|
entities: PropTypes.shape({
|
2016-07-19 19:13:51 +00:00
|
|
|
workspaces: PropTypes.object.isRequired,
|
|
|
|
settings: PropTypes.object.isRequired
|
2016-07-19 04:01:31 +00:00
|
|
|
}).isRequired,
|
|
|
|
actions: PropTypes.shape({
|
|
|
|
global: PropTypes.shape({
|
|
|
|
importFile: PropTypes.func.isRequired,
|
|
|
|
exportFile: PropTypes.func.isRequired,
|
|
|
|
})
|
2016-07-21 16:33:35 +00:00
|
|
|
}),
|
|
|
|
|
|
|
|
// Optional
|
|
|
|
selectedIndex: PropTypes.number
|
2016-07-19 04:01:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
function mapStateToProps (state) {
|
|
|
|
return {
|
|
|
|
workspaces: state.workspaces,
|
|
|
|
entities: state.entities,
|
|
|
|
actions: state.actions,
|
|
|
|
loading: state.global.loading
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function mapDispatchToProps (dispatch) {
|
|
|
|
return {
|
|
|
|
actions: {
|
|
|
|
global: bindActionCreators(GlobalActions, dispatch)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NOTE: We can't _connect_ the SettingsModal because it hides the public methods
|
|
|
|
const ConnectedSettingsTabs = connect(
|
|
|
|
mapStateToProps,
|
|
|
|
mapDispatchToProps
|
|
|
|
)(SettingsTabs);
|
|
|
|
|
|
|
|
|
2016-07-14 22:48:56 +00:00
|
|
|
class SettingsModal extends ModalComponent {
|
2016-07-21 16:33:35 +00:00
|
|
|
constructor (props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
|
|
|
selectedIndex: 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
show (selectedIndex = 0) {
|
|
|
|
super.show();
|
|
|
|
|
|
|
|
if (selectedIndex >= 0) {
|
|
|
|
this.setState({selectedIndex});
|
|
|
|
} else {
|
|
|
|
this.setState({selectedIndex: 0});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-07 20:10:55 +00:00
|
|
|
render () {
|
2016-07-21 16:33:35 +00:00
|
|
|
const {selectedIndex} = this.state;
|
2016-07-19 04:01:31 +00:00
|
|
|
|
2016-05-07 17:29:24 +00:00
|
|
|
return (
|
2016-07-07 20:10:55 +00:00
|
|
|
<Modal ref="modal" tall={true} {...this.props}>
|
2016-07-19 22:28:29 +00:00
|
|
|
<ModalHeader>
|
|
|
|
Insomnia
|
|
|
|
{" "}
|
|
|
|
<span className="faint txt-sm">v{getVersion()}</span>
|
|
|
|
</ModalHeader>
|
2016-07-07 20:10:55 +00:00
|
|
|
<ModalBody>
|
2016-07-21 16:33:35 +00:00
|
|
|
<ConnectedSettingsTabs selectedIndex={selectedIndex} />
|
2016-05-07 17:29:24 +00:00
|
|
|
</ModalBody>
|
2016-07-07 20:10:55 +00:00
|
|
|
<ModalFooter className="pad text-right">
|
|
|
|
<div className="relative">
|
|
|
|
Supported By
|
|
|
|
<Link href={MASHAPE_URL}>
|
|
|
|
<img src="images/mashape.png" style={{height: '1.5em'}} className="valign-bottom"/>
|
|
|
|
</Link>
|
|
|
|
</div>
|
|
|
|
</ModalFooter>
|
2016-05-07 17:29:24 +00:00
|
|
|
</Modal>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export default SettingsModal;
|