diff --git a/src/settings/actions/setting.js b/src/settings/actions/setting.js index c1b27c8..fa158a3 100644 --- a/src/settings/actions/setting.js +++ b/src/settings/actions/setting.js @@ -4,10 +4,10 @@ import DefaultSettings from 'shared/default-settings'; const load = () => { return browser.storage.local.get('settings').then(({ settings }) => { - if (settings) { - return set(settings); + if (!settings) { + return set(DefaultSettings); } - return set(DefaultSettings); + return set(Object.assign({}, DefaultSettings, settings)); }, console.error); }; @@ -28,6 +28,7 @@ const set = (settings) => { type: actions.SETTING_SET_SETTINGS, source: settings.source, json: settings.json, + form: settings.form, value: JSON.parse(settings.json), }; }; diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index 98d8fb2..11411bd 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -4,6 +4,59 @@ import Input from './ui/input'; import * as settingActions from 'settings/actions/setting'; import * as validator from 'shared/validators/setting'; +const KeyMapFields = [ + [ + ['scroll.vertically?{count:-1}', 'Scroll down'], + ['scroll.vertically?{count:1}', 'Scroll up'], + ['scroll.horizonally?{count:-1}', 'Scroll left'], + ['scroll.horizonally?{count:1}', 'Scroll right'], + ['scroll.home', 'Scroll leftmost'], + ['scroll.end', 'Scroll last'], + ['scroll.pages?{count:-0.5}', 'Scroll up by half of screen'], + ['scroll.pages?{count:0.5}', 'Scroll up by half of screen'], + ['scroll.pages?{count:-1}', 'Scroll up by a screen'], + ['scroll.pages?{count:1}', 'Scroll up by a screen'], + ], [ + ['tabs.close', 'Close a tab'], + ['tabs.reopen', 'Reopen closed tab'], + ['tabs.next?{count:1}', 'Select next Tab'], + ['tabs.prev?{count:1}', 'Select prev Tab'], + ['tabs.first', 'Select first tab'], + ['tabs.last', 'Select last tab'], + ['tabs.reload?{cache:true}', 'Reload current tab'], + ['tabs.pin.toggle', 'Toggle pinned state'], + ['tabs.duplicate', 'Dupplicate a tab'], + ], [ + ['follow.start?{newTab:false}', 'Follow a link'], + ['follow.start?{newTab:true}', 'Follow a link in new tab'], + ['navigate.histories.prev', 'Go back in histories'], + ['navigate.histories.next', 'Go forward in histories'], + ['navigate.link.next', 'Open next link'], + ['navigate.link.prev', 'Open previous link'], + ['navigate.parent', 'Go to parent directory'], + ['navigate.root', 'Go to root directory'], + ], [ + ['find.start', 'Start find mode'], + ['find.next', 'Find next word'], + ['find.prev', 'Find previous word'], + ], [ + ['command.show', 'Open console'], + ['command.show.open?{alter:false}', 'Open URL'], + ['command.show.open?{alter:true}', 'Alter URL'], + ['command.show.tabopen?{alter:false}', 'Open URL in new Tab'], + ['command.show.tabopen?{alter:true}', 'Alter URL in new Tab'], + ['command.show.winopen?{alter:false}', 'Open URL in new window'], + ['command.show.winopen?{alter:true}', 'Alter URL in new window'], + ['command.show.buffer', 'Open buffer command'], + ], [ + ['addon.toggle.enabled', 'Enable or disable'], + ['urls.yank', 'Copy current URL'], + ['zoom.in', 'Zoom-in'], + ['zoom.out', 'Zoom-out'], + ['zoom.neutral', 'Reset zoom level'], + ] +]; + class SettingsComponent extends Component { constructor(props, context) { super(props, context); @@ -29,33 +82,87 @@ class SettingsComponent extends Component { settings: { source: settings.source, json: settings.json, + form: settings.form, } }); } + renderFormFields() { + let keymapFields = KeyMapFields.map((group, index) => { + return
+ { + group.map((field) => { + let name = field[0]; + let label = field[1]; + let value = this.state.settings.form.keymaps[name]; + return ; + }) + } +
; + }); + + return
+
+ Keybindings +
+ { keymapFields } +
+
+
; + } + + renderJsonFields() { + return
+ +
; + } + render() { + let fields = null; + if (this.state.settings.source === 'form') { + fields = this.renderFormFields(); + } else if (this.state.settings.source === 'json') { + fields = this.renderJsonFields(); + } return (

Configure Vim-Vixen

+ + value='json' + onChange={this.bindValue.bind(this)} /> - + { fields }
); @@ -82,9 +189,15 @@ class SettingsComponent extends Component { this.setState(next); } - bindAndSave(e) { - this.bindValue(e); + bindFormKeymapsValue(e) { + let next = Object.assign({}, this.state); + + next.settings.form.keymaps[e.target.name] = e.target.value; + + this.context.store.dispatch(settingActions.save(next.settings)); + } + save() { try { let json = this.state.settings.json; validator.validate(JSON.parse(json)); diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss index aac4319..dcc52ce 100644 --- a/src/settings/components/site.scss +++ b/src/settings/components/site.scss @@ -7,4 +7,31 @@ min-height: 64ex; resize: vertical; } + + fieldset { + margin: 0; + padding: 0; + border: none; + margin-top: 1rem; + + fieldset:first-of-type { + margin-top: 1rem; + } + + legend { + font-size: 1.5rem; + line-height: 1.5rem; + font-weight: bold; + } + } + + .keymap-fields{ + column-count: 2; + .keymap-fields-group { + margin-top: 24px; + } + .keymap-fields-group:first-of-type { + margin-top: 0; + } + } } diff --git a/src/settings/components/ui/input.jsx b/src/settings/components/ui/input.jsx index 9b6c229..5138411 100644 --- a/src/settings/components/ui/input.jsx +++ b/src/settings/components/ui/input.jsx @@ -3,32 +3,35 @@ import './input.scss'; class Input extends Component { + renderText(props) { + let inputClassName = props.error ? 'input-error' : ''; + return
+ + +
; + } + renderRadio(props) { - let inputClasses = 'form-field-input'; - if (props.error) { - inputClasses += ' input-error'; - } - return
+ let inputClassName = props.error ? 'input-error' : ''; + return
; } renderTextArea(props) { - let inputClasses = 'form-field-input'; - if (props.error) { - inputClasses += ' input-error'; - } - return
+ let inputClassName = props.error ? 'input-error' : ''; + return
-