From 7b44b652473b487e2d00a5b705a7f78ee66dec65 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Thu, 23 Nov 2017 21:22:42 +0900 Subject: Add search form --- .../components/form/search-engine-form.jsx | 69 ++++++++++++++++++++++ .../components/form/search-engine-form.scss | 38 ++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/settings/components/form/search-engine-form.jsx create mode 100644 src/settings/components/form/search-engine-form.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/search-engine-form.jsx b/src/settings/components/form/search-engine-form.jsx new file mode 100644 index 0000000..77da304 --- /dev/null +++ b/src/settings/components/form/search-engine-form.jsx @@ -0,0 +1,69 @@ +import { h, Component } from 'preact'; +import './search-engine-form.scss'; + +class SearchEngineForm extends Component { + + render() { + let value = this.props.value; + if (!value) { + value = { default: '', engines: []}; + } + let { + default: defaultEngine, + engines + } = value; + + return
+
+
Name
+
URL
+
Default
+
+ { + engines.map((engine, index) => { + return
+ + +
+ + +
+
; + }) + } +
; + } + + bindValue(e) { + if (!this.props.onChange) { + return; + } + + let name = e.target.name; + let index = e.target.getAttribute('data-index'); + let next = Object.assign({}, this.props.value); + + if (name === 'name') { + next.engines[index][0] = e.target.value; + } else if (name === 'url') { + next.engines[index][1] = e.target.value; + } else if (name === 'default') { + next.default = this.props.value.engines[index][0]; + } else if (name === 'delete') { + next.engines.splice(index, 1); + } + + this.props.onChange(next); + } +} + +export default SearchEngineForm; diff --git a/src/settings/components/form/search-engine-form.scss b/src/settings/components/form/search-engine-form.scss new file mode 100644 index 0000000..1ca43b7 --- /dev/null +++ b/src/settings/components/form/search-engine-form.scss @@ -0,0 +1,38 @@ +.form-search-engine-form { + @mixin row-base { + display: flex; + + .column-name { + flex: 1; + } + .column-url { + flex: 5; + } + .column-option { + text-align: right; + flex-basis: 5rem; + } + } + + &-header { + @include row-base; + + font-weight: bold; + } + + &-row { + @include row-base; + + .column-option input[type='button'] { + border: none; + padding: 4; + display: inline; + background: none; + color: red; + + &:hover { + color: darkred; + } + } + } +} -- cgit v1.2.3 From 2641183a5b244a9640d8fb7e92ba95dc15dadc58 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 12:31:24 +0900 Subject: keymaps form --- src/settings/components/form/keymaps-form.jsx | 95 +++++++++++++++++++++++++ src/settings/components/form/keymaps-form.scss | 9 +++ src/settings/components/index.jsx | 97 ++++---------------------- src/settings/components/site.scss | 10 --- 4 files changed, 116 insertions(+), 95 deletions(-) create mode 100644 src/settings/components/form/keymaps-form.jsx create mode 100644 src/settings/components/form/keymaps-form.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx new file mode 100644 index 0000000..a112979 --- /dev/null +++ b/src/settings/components/form/keymaps-form.jsx @@ -0,0 +1,95 @@ +import './keymaps-form.scss'; +import { h, Component } from 'preact'; +import Input from '../ui/input'; + +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 KeymapsForm extends Component { + + render() { + return
+ { + KeyMapFields.map((group, index) => { + return
+ { + group.map((field) => { + let name = field[0]; + let label = field[1]; + let value = this.props.value[name]; + return ; + }) + } +
; + }) + } +
; + } + + bindValue(e) { + if (!this.props.onChange) { + return; + } + + let next = Object.assign({}, this.props.value); + next[e.target.name] = e.target.value; + + this.props.onChange(next); + } +} + +export default KeymapsForm; diff --git a/src/settings/components/form/keymaps-form.scss b/src/settings/components/form/keymaps-form.scss new file mode 100644 index 0000000..8b86c80 --- /dev/null +++ b/src/settings/components/form/keymaps-form.scss @@ -0,0 +1,9 @@ +.form-keymaps-form { + column-count: 2; + .keymap-fields-group { + margin-top: 24px; + } + .keymap-fields-group:first-of-type { + margin-top: 0; + } +} diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index 8fe7d4d..e5b46ad 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -2,62 +2,10 @@ import './site.scss'; import { h, Component } from 'preact'; import Input from './ui/input'; import SearchEngineForm from './form/search-engine-form'; +import KeymapsForm from './form/keymaps-form'; 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); @@ -89,33 +37,13 @@ class SettingsComponent extends Component { } 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 } -
+
Search Engines @@ -189,6 +117,13 @@ class SettingsComponent extends Component { this.context.store.dispatch(settingActions.save(next.settings)); } + bindKeymapsForm(value) { + let next = Object.assign({}, this.state); + next.settings.form.keymaps = value; + this.setState(next); + this.context.store.dispatch(settingActions.save(next.settings)); + } + bindValue(e) { let next = Object.assign({}, this.state); @@ -203,14 +138,6 @@ class SettingsComponent extends Component { this.setState(next); this.context.store.dispatch(settingActions.save(next.settings)); } - - 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)); - } } export default SettingsComponent; diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss index dcc52ce..c8dd422 100644 --- a/src/settings/components/site.scss +++ b/src/settings/components/site.scss @@ -24,14 +24,4 @@ font-weight: bold; } } - - .keymap-fields{ - column-count: 2; - .keymap-fields-group { - margin-top: 24px; - } - .keymap-fields-group:first-of-type { - margin-top: 0; - } - } } -- cgit v1.2.3 From bbad1c6c6adf65de031111340f8bf5e46cc41ca6 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 13:58:25 +0900 Subject: delete button --- src/settings/components/form/search-engine-form.jsx | 6 +++--- src/settings/components/form/search-engine-form.scss | 12 ------------ src/settings/components/ui/delete-button.jsx | 12 ++++++++++++ src/settings/components/ui/delete-button.scss | 12 ++++++++++++ 4 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 src/settings/components/ui/delete-button.jsx create mode 100644 src/settings/components/ui/delete-button.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/search-engine-form.jsx b/src/settings/components/form/search-engine-form.jsx index 77da304..c86522a 100644 --- a/src/settings/components/form/search-engine-form.jsx +++ b/src/settings/components/form/search-engine-form.jsx @@ -1,5 +1,6 @@ -import { h, Component } from 'preact'; import './search-engine-form.scss'; +import { h, Component } from 'preact'; +import DeleteButton from '../ui/delete-button'; class SearchEngineForm extends Component { @@ -33,8 +34,7 @@ class SearchEngineForm extends Component { -
; diff --git a/src/settings/components/form/search-engine-form.scss b/src/settings/components/form/search-engine-form.scss index 1ca43b7..0d33c23 100644 --- a/src/settings/components/form/search-engine-form.scss +++ b/src/settings/components/form/search-engine-form.scss @@ -22,17 +22,5 @@ &-row { @include row-base; - - .column-option input[type='button'] { - border: none; - padding: 4; - display: inline; - background: none; - color: red; - - &:hover { - color: darkred; - } - } } } diff --git a/src/settings/components/ui/delete-button.jsx b/src/settings/components/ui/delete-button.jsx new file mode 100644 index 0000000..8077a76 --- /dev/null +++ b/src/settings/components/ui/delete-button.jsx @@ -0,0 +1,12 @@ +import './delete-button.scss'; +import { h, Component } from 'preact'; + +class DeleteButton extends Component { + render() { + return ; + } +} + +export default DeleteButton; diff --git a/src/settings/components/ui/delete-button.scss b/src/settings/components/ui/delete-button.scss new file mode 100644 index 0000000..7aa2f39 --- /dev/null +++ b/src/settings/components/ui/delete-button.scss @@ -0,0 +1,12 @@ + +.ui-delete-button { + border: none; + padding: 4; + display: inline; + background: none; + color: red; + + &:hover { + color: darkred; + } +} -- cgit v1.2.3 From df10208ed5dfbc823eb1979272903d74f02a898c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 14:59:03 +0900 Subject: blacklist form --- src/settings/components/form/blacklist-form.jsx | 47 ++++++++++++++++++++++++ src/settings/components/form/blacklist-form.scss | 9 +++++ src/settings/components/index.jsx | 29 +++++++++------ src/shared/default-settings.js | 3 +- 4 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 src/settings/components/form/blacklist-form.jsx create mode 100644 src/settings/components/form/blacklist-form.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/blacklist-form.jsx b/src/settings/components/form/blacklist-form.jsx new file mode 100644 index 0000000..83b54da --- /dev/null +++ b/src/settings/components/form/blacklist-form.jsx @@ -0,0 +1,47 @@ +import './blacklist-form.scss'; +import DeleteButton from '../ui/delete-button'; +import { h, Component } from 'preact'; + +class BlacklistForm extends Component { + + render() { + let value = this.props.value; + if (!value) { + value = []; + } + + return
+ { + value.map((url, index) => { + return
+ + +
; + }) + } +
; + } + + bindValue(e) { + if (!this.props.onChange) { + return; + } + + let name = e.target.name; + let index = e.target.getAttribute('data-index'); + let next = this.props.value.slice(); + + if (name === 'url') { + next[index] = e.target.value; + } else if (name === 'delete') { + next.splice(index, 1); + } + + this.props.onChange(next); + } +} + +export default BlacklistForm; diff --git a/src/settings/components/form/blacklist-form.scss b/src/settings/components/form/blacklist-form.scss new file mode 100644 index 0000000..a230d0d --- /dev/null +++ b/src/settings/components/form/blacklist-form.scss @@ -0,0 +1,9 @@ +.form-blacklist-form { + &-row { + display: flex; + + .column-url { + flex: 1; + } + } +} diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index e5b46ad..fb25df6 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -3,6 +3,7 @@ import { h, Component } from 'preact'; import Input from './ui/input'; import SearchEngineForm from './form/search-engine-form'; import KeymapsForm from './form/keymaps-form'; +import BlacklistForm from './form/blacklist-form'; import * as settingActions from 'settings/actions/setting'; import * as validator from 'shared/validators/setting'; @@ -42,14 +43,21 @@ class SettingsComponent extends Component { Keybindings this.bindForm('keymaps', value)} />
Search Engines this.bindForm('search', value)} + /> +
+
+ Blacklist + this.bindForm('blacklist', value)} />
; @@ -110,16 +118,13 @@ class SettingsComponent extends Component { } } - bindSearchForm(value) { - let next = Object.assign({}, this.state); - next.settings.form.search = value; - this.setState(next); - this.context.store.dispatch(settingActions.save(next.settings)); - } - - bindKeymapsForm(value) { - let next = Object.assign({}, this.state); - next.settings.form.keymaps = value; + bindForm(name, value) { + let next = Object.assign({}, this.state, { + settings: Object.assign({}, this.state.settings, { + form: Object.assign({}, this.state.settings.form) + }) + }); + next.settings.form[name] = value; this.setState(next); this.context.store.dispatch(settingActions.save(next.settings)); } diff --git a/src/shared/default-settings.js b/src/shared/default-settings.js index 6d2013b..218390b 100644 --- a/src/shared/default-settings.js +++ b/src/shared/default-settings.js @@ -125,6 +125,7 @@ export default { ['twitter', 'https,//twitter.com/search?q={}'], ['wikipedia', 'https,//en.wikipedia.org/w/index.php?search={}'], ] - } + }, + 'blacklist': [], } }; -- cgit v1.2.3 From 507000619377f82ca63251c8c5db98af690a5ed2 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 15:08:41 +0900 Subject: add button --- src/settings/components/form/blacklist-form.jsx | 4 ++++ src/settings/components/form/search-engine-form.jsx | 4 ++++ src/settings/components/ui/add-button.jsx | 12 ++++++++++++ src/settings/components/ui/add-button.scss | 3 +++ 4 files changed, 23 insertions(+) create mode 100644 src/settings/components/ui/add-button.jsx create mode 100644 src/settings/components/ui/add-button.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/blacklist-form.jsx b/src/settings/components/form/blacklist-form.jsx index 83b54da..9cb547b 100644 --- a/src/settings/components/form/blacklist-form.jsx +++ b/src/settings/components/form/blacklist-form.jsx @@ -1,4 +1,5 @@ import './blacklist-form.scss'; +import AddButton from '../ui/add-button'; import DeleteButton from '../ui/delete-button'; import { h, Component } from 'preact'; @@ -22,6 +23,7 @@ class BlacklistForm extends Component { ; }) } + ; } @@ -36,6 +38,8 @@ class BlacklistForm extends Component { if (name === 'url') { next[index] = e.target.value; + } else if (name === 'add') { + next.push(''); } else if (name === 'delete') { next.splice(index, 1); } diff --git a/src/settings/components/form/search-engine-form.jsx b/src/settings/components/form/search-engine-form.jsx index c86522a..faa066f 100644 --- a/src/settings/components/form/search-engine-form.jsx +++ b/src/settings/components/form/search-engine-form.jsx @@ -1,5 +1,6 @@ import './search-engine-form.scss'; import { h, Component } from 'preact'; +import AddButton from '../ui/add-button'; import DeleteButton from '../ui/delete-button'; class SearchEngineForm extends Component { @@ -40,6 +41,7 @@ class SearchEngineForm extends Component { ; }) } + ; } @@ -58,6 +60,8 @@ class SearchEngineForm extends Component { next.engines[index][1] = e.target.value; } else if (name === 'default') { next.default = this.props.value.engines[index][0]; + } else if (name === 'add') { + next.engines.push(['', '']); } else if (name === 'delete') { next.engines.splice(index, 1); } diff --git a/src/settings/components/ui/add-button.jsx b/src/settings/components/ui/add-button.jsx new file mode 100644 index 0000000..c8d8856 --- /dev/null +++ b/src/settings/components/ui/add-button.jsx @@ -0,0 +1,12 @@ +import './add-button.scss'; +import { h, Component } from 'preact'; + +class AddButton extends Component { + render() { + return ; + } +} + +export default AddButton; diff --git a/src/settings/components/ui/add-button.scss b/src/settings/components/ui/add-button.scss new file mode 100644 index 0000000..1c893ae --- /dev/null +++ b/src/settings/components/ui/add-button.scss @@ -0,0 +1,3 @@ +.ui-add-button { + font-size: 80% +} -- cgit v1.2.3 From f27d21908a2b402e3274288d4411a48160f38e4c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 18:03:15 +0900 Subject: load settiongs from form --- src/settings/actions/setting.js | 12 ++- src/settings/components/form/keymaps-form.jsx | 38 ++++---- src/shared/default-settings.js | 131 -------------------------- src/shared/settings/default.js | 131 ++++++++++++++++++++++++++ src/shared/settings/values.js | 35 +++++++ 5 files changed, 195 insertions(+), 152 deletions(-) delete mode 100644 src/shared/default-settings.js create mode 100644 src/shared/settings/default.js create mode 100644 src/shared/settings/values.js (limited to 'src/settings/components/form') diff --git a/src/settings/actions/setting.js b/src/settings/actions/setting.js index fa158a3..1d4ef34 100644 --- a/src/settings/actions/setting.js +++ b/src/settings/actions/setting.js @@ -1,6 +1,7 @@ import actions from 'settings/actions'; import messages from 'shared/messages'; -import DefaultSettings from 'shared/default-settings'; +import DefaultSettings from 'shared/settings/default'; +import * as settingsValues from 'shared/settings/values'; const load = () => { return browser.storage.local.get('settings').then(({ settings }) => { @@ -24,12 +25,19 @@ const save = (settings) => { }; const set = (settings) => { + let value = JSON.parse(DefaultSettings.json); + if (settings.source === 'json') { + value = settingsValues.fromJson(settings.json); + } else if (settings.source === 'form') { + value = settingsValues.fromForm(settings.form); + } + return { type: actions.SETTING_SET_SETTINGS, source: settings.source, json: settings.json, form: settings.form, - value: JSON.parse(settings.json), + value, }; }; diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index a112979..a827e4e 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -4,29 +4,29 @@ import Input from '../ui/input'; 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.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'], + ['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.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.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'], + ['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'], @@ -39,12 +39,12 @@ const KeyMapFields = [ ['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.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'], diff --git a/src/shared/default-settings.js b/src/shared/default-settings.js deleted file mode 100644 index 218390b..0000000 --- a/src/shared/default-settings.js +++ /dev/null @@ -1,131 +0,0 @@ -export default { - source: 'json', - json: `{ - "keymaps": { - "0": { "type": "scroll.home" }, - ":": { "type": "command.show" }, - "o": { "type": "command.show.open", "alter": false }, - "O": { "type": "command.show.open", "alter": true }, - "t": { "type": "command.show.tabopen", "alter": false }, - "T": { "type": "command.show.tabopen", "alter": true }, - "w": { "type": "command.show.winopen", "alter": false }, - "W": { "type": "command.show.winopen", "alter": true }, - "b": { "type": "command.show.buffer" }, - "k": { "type": "scroll.vertically", "count": -1 }, - "j": { "type": "scroll.vertically", "count": 1 }, - "h": { "type": "scroll.horizonally", "count": -1 }, - "l": { "type": "scroll.horizonally", "count": 1 }, - "": { "type": "scroll.vertically", "count": -1 }, - "": { "type": "scroll.vertically", "count": 1 }, - "": { "type": "scroll.pages", "count": -0.5 }, - "": { "type": "scroll.pages", "count": 0.5 }, - "": { "type": "scroll.pages", "count": -1 }, - "": { "type": "scroll.pages", "count": 1 }, - "gg": { "type": "scroll.top" }, - "G": { "type": "scroll.bottom" }, - "$": { "type": "scroll.end" }, - "d": { "type": "tabs.close" }, - "u": { "type": "tabs.reopen" }, - "K": { "type": "tabs.prev", "count": 1 }, - "J": { "type": "tabs.next", "count": 1 }, - "g0": { "type": "tabs.first" }, - "g$": { "type": "tabs.last" }, - "r": { "type": "tabs.reload", "cache": false }, - "R": { "type": "tabs.reload", "cache": true }, - "zp": { "type": "tabs.pin.toggle" }, - "zd": { "type": "tabs.duplicate" }, - "zi": { "type": "zoom.in" }, - "zo": { "type": "zoom.out" }, - "zz": { "type": "zoom.neutral" }, - "f": { "type": "follow.start", "newTab": false }, - "F": { "type": "follow.start", "newTab": true }, - "H": { "type": "navigate.history.prev" }, - "L": { "type": "navigate.history.next" }, - "[[": { "type": "navigate.link.prev" }, - "]]": { "type": "navigate.link.next" }, - "gu": { "type": "navigate.parent" }, - "gU": { "type": "navigate.root" }, - "y": { "type": "urls.yank" }, - "/": { "type": "find.start" }, - "n": { "type": "find.next" }, - "N": { "type": "find.prev" }, - "": { "type": "addon.toggle.enabled" } - }, - "search": { - "default": "google", - "engines": { - "google": "https://google.com/search?q={}", - "yahoo": "https://search.yahoo.com/search?p={}", - "bing": "https://www.bing.com/search?q={}", - "duckduckgo": "https://duckduckgo.com/?q={}", - "twitter": "https://twitter.com/search?q={}", - "wikipedia": "https://en.wikipedia.org/w/index.php?search={}" - } - } -}`, - - 'form': { - 'keymaps': { - 'scroll.vertically?{count:-1}': 'j', - 'scroll.vertically?{count:1}': 'k', - 'scroll.horizonally?{count:-1}': 'h', - 'scroll.horizonally?{count:1}': 'l', - 'scroll.home': '0', - 'scroll.end': '$', - 'scroll.pages?{count:-0.5}': '', - 'scroll.pages?{count:0.5}': '', - 'scroll.pages?{count:-1}': '', - 'scroll.pages?{count:1}': '', - - 'tabs.close': 'd', - 'tabs.reopen': 'u', - 'tabs.next?{count:1}': 'J', - 'tabs.prev?{count:1}': 'K', - 'tabs.first': 'g0', - 'tabs.last': 'g$', - 'tabs.reload?{cache:true}': 'r', - 'tabs.pin.toggle': 'zp', - 'tabs.duplicate': 'zd', - - 'follow.start?{newTab:false}': 'f', - 'follow.start?{newTab:true}': 'F', - 'navigate.histories.prev': 'H', - 'navigate.histories.next': 'L', - 'navigate.link.next': ']]', - 'navigate.link.prev': '[[', - 'navigate.parent': 'gu', - 'navigate.root': 'gU', - - 'find.start': '/', - 'find.next': 'n', - 'find.prev': 'N', - - 'command.show': ':', - 'command.show.open?{alter:false}': 'o', - 'command.show.open?{alter:true}': 'O', - 'command.show.tabopen?{alter:false}': 't', - 'command.show.tabopen?{alter:true}': 'T', - 'command.show.winopen?{alter:false}': 'w', - 'command.show.winopen?{alter:true}': 'W', - 'command.show.buffer': 'b', - - 'addon.toggle.enabled': '', - 'urls.yank': 'y', - 'zoom.in': 'zi', - 'zoom.out': 'zo', - 'zoom.neutral': 'zz', - }, - 'search': { - 'default': 'google', - 'engines': [ - ['google', 'https,//google.com/search?q={}'], - ['yahoo', 'https,//search.yahoo.com/search?p={}'], - ['bing', 'https,//www.bing.com/search?q={}'], - ['duckduckgo', 'https,//duckduckgo.com/?q={}'], - ['twitter', 'https,//twitter.com/search?q={}'], - ['wikipedia', 'https,//en.wikipedia.org/w/index.php?search={}'], - ] - }, - 'blacklist': [], - } -}; diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js new file mode 100644 index 0000000..fc259b8 --- /dev/null +++ b/src/shared/settings/default.js @@ -0,0 +1,131 @@ +export default { + source: 'json', + json: `{ + "keymaps": { + "0": { "type": "scroll.home" }, + ":": { "type": "command.show" }, + "o": { "type": "command.show.open", "alter": false }, + "O": { "type": "command.show.open", "alter": true }, + "t": { "type": "command.show.tabopen", "alter": false }, + "T": { "type": "command.show.tabopen", "alter": true }, + "w": { "type": "command.show.winopen", "alter": false }, + "W": { "type": "command.show.winopen", "alter": true }, + "b": { "type": "command.show.buffer" }, + "k": { "type": "scroll.vertically", "count": -1 }, + "j": { "type": "scroll.vertically", "count": 1 }, + "h": { "type": "scroll.horizonally", "count": -1 }, + "l": { "type": "scroll.horizonally", "count": 1 }, + "": { "type": "scroll.vertically", "count": -1 }, + "": { "type": "scroll.vertically", "count": 1 }, + "": { "type": "scroll.pages", "count": -0.5 }, + "": { "type": "scroll.pages", "count": 0.5 }, + "": { "type": "scroll.pages", "count": -1 }, + "": { "type": "scroll.pages", "count": 1 }, + "gg": { "type": "scroll.top" }, + "G": { "type": "scroll.bottom" }, + "$": { "type": "scroll.end" }, + "d": { "type": "tabs.close" }, + "u": { "type": "tabs.reopen" }, + "K": { "type": "tabs.prev", "count": 1 }, + "J": { "type": "tabs.next", "count": 1 }, + "g0": { "type": "tabs.first" }, + "g$": { "type": "tabs.last" }, + "r": { "type": "tabs.reload", "cache": false }, + "R": { "type": "tabs.reload", "cache": true }, + "zp": { "type": "tabs.pin.toggle" }, + "zd": { "type": "tabs.duplicate" }, + "zi": { "type": "zoom.in" }, + "zo": { "type": "zoom.out" }, + "zz": { "type": "zoom.neutral" }, + "f": { "type": "follow.start", "newTab": false }, + "F": { "type": "follow.start", "newTab": true }, + "H": { "type": "navigate.history.prev" }, + "L": { "type": "navigate.history.next" }, + "[[": { "type": "navigate.link.prev" }, + "]]": { "type": "navigate.link.next" }, + "gu": { "type": "navigate.parent" }, + "gU": { "type": "navigate.root" }, + "y": { "type": "urls.yank" }, + "/": { "type": "find.start" }, + "n": { "type": "find.next" }, + "N": { "type": "find.prev" }, + "": { "type": "addon.toggle.enabled" } + }, + "search": { + "default": "google", + "engines": { + "google": "https://google.com/search?q={}", + "yahoo": "https://search.yahoo.com/search?p={}", + "bing": "https://www.bing.com/search?q={}", + "duckduckgo": "https://duckduckgo.com/?q={}", + "twitter": "https://twitter.com/search?q={}", + "wikipedia": "https://en.wikipedia.org/w/index.php?search={}" + } + } +}`, + + 'form': { + 'keymaps': { + 'scroll.vertically?{"count":1}': 'j', + 'scroll.vertically?{"count":-1}': 'k', + 'scroll.horizonally?{"count":-1}': 'h', + 'scroll.horizonally?{"count":1}': 'l', + 'scroll.home': '0', + 'scroll.end': '$', + 'scroll.pages?{"count":-0.5}': '', + 'scroll.pages?{"count":0.5}': '', + 'scroll.pages?{"count":-1}': '', + 'scroll.pages?{"count":1}': '', + + 'tabs.close': 'd', + 'tabs.reopen': 'u', + 'tabs.next?{"count":1}': 'J', + 'tabs.prev?{"count":1}': 'K', + 'tabs.first': 'g0', + 'tabs.last': 'g$', + 'tabs.reload?{"cache":true}': 'r', + 'tabs.pin.toggle': 'zp', + 'tabs.duplicate': 'zd', + + 'follow.start?{"newTab":false}': 'f', + 'follow.start?{"newTab":true}': 'F', + 'navigate.histories.prev': 'H', + 'navigate.histories.next': 'L', + 'navigate.link.next': ']]', + 'navigate.link.prev': '[[', + 'navigate.parent': 'gu', + 'navigate.root': 'gU', + + 'find.start': '/', + 'find.next': 'n', + 'find.prev': 'N', + + 'command.show': ':', + 'command.show.open?{"alter":false}': 'o', + 'command.show.open?{"alter":true}': 'O', + 'command.show.tabopen?{"alter":false}': 't', + 'command.show.tabopen?{"alter":true}': 'T', + 'command.show.winopen?{"alter":false}': 'w', + 'command.show.winopen?{"alter":true}': 'W', + 'command.show.buffer': 'b', + + 'addon.toggle.enabled': '', + 'urls.yank': 'y', + 'zoom.in': 'zi', + 'zoom.out': 'zo', + 'zoom.neutral': 'zz', + }, + 'search': { + 'default': 'google', + 'engines': [ + ['google', 'https,//google.com/search?q={}'], + ['yahoo', 'https,//search.yahoo.com/search?p={}'], + ['bing', 'https,//www.bing.com/search?q={}'], + ['duckduckgo', 'https,//duckduckgo.com/?q={}'], + ['twitter', 'https,//twitter.com/search?q={}'], + ['wikipedia', 'https,//en.wikipedia.org/w/index.php?search={}'], + ] + }, + 'blacklist': [], + } +}; diff --git a/src/shared/settings/values.js b/src/shared/settings/values.js new file mode 100644 index 0000000..d86cfdc --- /dev/null +++ b/src/shared/settings/values.js @@ -0,0 +1,35 @@ +const operationFromName = (name) => { + let [type, argStr] = name.split('?'); + let args = {}; + if (argStr) { + args = JSON.parse(argStr); + } + return Object.assign({ type }, args); +}; + +const fromJson = (json) => { + return JSON.parse(json); +}; + +const fromForm = (form) => { + let keymaps = {}; + for (let name of Object.keys(form.keymaps)) { + let keys = form.keymaps[name]; + keymaps[keys] = operationFromName(name); + } + + let engines = {}; + for (let { name, url } of form.search.engines) { + engines[name] = url; + } + let search = { + default: form.search.default, + engines, + }; + + let blacklist = form.blacklist; + + return { keymaps, search, blacklist }; +}; + +export { fromJson, fromForm }; -- cgit v1.2.3 From 2c46e9d448142c84b802ef8e0e1af53524dc4759 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 25 Nov 2017 22:58:10 +0900 Subject: fix keymap form --- src/settings/components/form/keymaps-form.jsx | 4 ++-- src/shared/settings/default.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index a827e4e..8e93c3f 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -27,8 +27,8 @@ const KeyMapFields = [ ], [ ['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.history.prev', 'Go back in histories'], + ['navigate.history.next', 'Go forward in histories'], ['navigate.link.next', 'Open next link'], ['navigate.link.prev', 'Open previous link'], ['navigate.parent', 'Go to parent directory'], diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index fc259b8..69238e3 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -89,8 +89,8 @@ export default { 'follow.start?{"newTab":false}': 'f', 'follow.start?{"newTab":true}': 'F', - 'navigate.histories.prev': 'H', - 'navigate.histories.next': 'L', + 'navigate.history.prev': 'H', + 'navigate.history.next': 'L', 'navigate.link.next': ']]', 'navigate.link.prev': '[[', 'navigate.parent': 'gu', -- cgit v1.2.3 From 256e7372d4a96079b993115eabde8b33d400c7c8 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 08:25:23 +0900 Subject: settings migration between json and form --- src/settings/components/form/blacklist-form.jsx | 2 +- src/settings/components/index.jsx | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/blacklist-form.jsx b/src/settings/components/form/blacklist-form.jsx index 9cb547b..4333929 100644 --- a/src/settings/components/form/blacklist-form.jsx +++ b/src/settings/components/form/blacklist-form.jsx @@ -34,7 +34,7 @@ class BlacklistForm extends Component { let name = e.target.name; let index = e.target.getAttribute('data-index'); - let next = this.props.value.slice(); + let next = this.props.value ? this.props.value.slice() : []; if (name === 'url') { next[index] = e.target.value; diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index fb25df6..ae7cd31 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -6,6 +6,7 @@ import KeymapsForm from './form/keymaps-form'; import BlacklistForm from './form/blacklist-form'; import * as settingActions from 'settings/actions/setting'; import * as validator from 'shared/validators/setting'; +import * as settingsValues from 'shared/settings/values'; class SettingsComponent extends Component { constructor(props, context) { @@ -95,7 +96,7 @@ class SettingsComponent extends Component { label='Use form' checked={this.state.settings.source === 'form'} value='form' - onChange={this.bindValue.bind(this)} /> + onChange={this.bindSource.bind(this)} /> + onChange={this.bindSource.bind(this)} /> { fields } @@ -143,6 +144,24 @@ class SettingsComponent extends Component { this.setState(next); this.context.store.dispatch(settingActions.save(next.settings)); } + + bindSource(e) { + let from = this.state.settings.source; + let to = e.target.value; + + let next = Object.assign({}, this.state); + if (from === 'form' && to === 'json') { + next.settings.json = + settingsValues.jsonFromForm(this.state.settings.form); + } else if (from === 'json' && to === 'form') { + next.settings.form = + settingsValues.formFromJson(this.state.settings.json); + } + next.settings.source = to; + + this.setState(next); + this.context.store.dispatch(settingActions.save(next.settings)); + } } export default SettingsComponent; -- cgit v1.2.3 From d195890eb957e5b6e40f7c01ce34d07e7ccf22b5 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 11:37:25 +0900 Subject: rename serach engine --- .../components/form/search-engine-form.jsx | 73 ---------------------- .../components/form/search-engine-form.scss | 26 -------- src/settings/components/form/search-form.jsx | 73 ++++++++++++++++++++++ src/settings/components/form/search-form.scss | 26 ++++++++ src/settings/components/index.jsx | 4 +- 5 files changed, 101 insertions(+), 101 deletions(-) delete mode 100644 src/settings/components/form/search-engine-form.jsx delete mode 100644 src/settings/components/form/search-engine-form.scss create mode 100644 src/settings/components/form/search-form.jsx create mode 100644 src/settings/components/form/search-form.scss (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/search-engine-form.jsx b/src/settings/components/form/search-engine-form.jsx deleted file mode 100644 index faa066f..0000000 --- a/src/settings/components/form/search-engine-form.jsx +++ /dev/null @@ -1,73 +0,0 @@ -import './search-engine-form.scss'; -import { h, Component } from 'preact'; -import AddButton from '../ui/add-button'; -import DeleteButton from '../ui/delete-button'; - -class SearchEngineForm extends Component { - - render() { - let value = this.props.value; - if (!value) { - value = { default: '', engines: []}; - } - let { - default: defaultEngine, - engines - } = value; - - return
-
-
Name
-
URL
-
Default
-
- { - engines.map((engine, index) => { - return
- - -
- - -
-
; - }) - } - -
; - } - - bindValue(e) { - if (!this.props.onChange) { - return; - } - - let name = e.target.name; - let index = e.target.getAttribute('data-index'); - let next = Object.assign({}, this.props.value); - - if (name === 'name') { - next.engines[index][0] = e.target.value; - } else if (name === 'url') { - next.engines[index][1] = e.target.value; - } else if (name === 'default') { - next.default = this.props.value.engines[index][0]; - } else if (name === 'add') { - next.engines.push(['', '']); - } else if (name === 'delete') { - next.engines.splice(index, 1); - } - - this.props.onChange(next); - } -} - -export default SearchEngineForm; diff --git a/src/settings/components/form/search-engine-form.scss b/src/settings/components/form/search-engine-form.scss deleted file mode 100644 index 0d33c23..0000000 --- a/src/settings/components/form/search-engine-form.scss +++ /dev/null @@ -1,26 +0,0 @@ -.form-search-engine-form { - @mixin row-base { - display: flex; - - .column-name { - flex: 1; - } - .column-url { - flex: 5; - } - .column-option { - text-align: right; - flex-basis: 5rem; - } - } - - &-header { - @include row-base; - - font-weight: bold; - } - - &-row { - @include row-base; - } -} diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx new file mode 100644 index 0000000..9bafb8d --- /dev/null +++ b/src/settings/components/form/search-form.jsx @@ -0,0 +1,73 @@ +import './search-form.scss'; +import { h, Component } from 'preact'; +import AddButton from '../ui/add-button'; +import DeleteButton from '../ui/delete-button'; + +class SearchForm extends Component { + + render() { + let value = this.props.value; + if (!value) { + value = { default: '', engines: []}; + } + let { + default: defaultEngine, + engines + } = value; + + return
+
+
Name
+
URL
+
Default
+
+ { + engines.map((engine, index) => { + return
+ + +
+ + +
+
; + }) + } + +
; + } + + bindValue(e) { + if (!this.props.onChange) { + return; + } + + let name = e.target.name; + let index = e.target.getAttribute('data-index'); + let next = Object.assign({}, this.props.value); + + if (name === 'name') { + next.engines[index][0] = e.target.value; + } else if (name === 'url') { + next.engines[index][1] = e.target.value; + } else if (name === 'default') { + next.default = this.props.value.engines[index][0]; + } else if (name === 'add') { + next.engines.push(['', '']); + } else if (name === 'delete') { + next.engines.splice(index, 1); + } + + this.props.onChange(next); + } +} + +export default SearchForm; diff --git a/src/settings/components/form/search-form.scss b/src/settings/components/form/search-form.scss new file mode 100644 index 0000000..8814ef5 --- /dev/null +++ b/src/settings/components/form/search-form.scss @@ -0,0 +1,26 @@ +.form-search-form { + @mixin row-base { + display: flex; + + .column-name { + flex: 1; + } + .column-url { + flex: 5; + } + .column-option { + text-align: right; + flex-basis: 5rem; + } + } + + &-header { + @include row-base; + + font-weight: bold; + } + + &-row { + @include row-base; + } +} diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index ae7cd31..b7de259 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -1,7 +1,7 @@ import './site.scss'; import { h, Component } from 'preact'; import Input from './ui/input'; -import SearchEngineForm from './form/search-engine-form'; +import SearchForm from './form/search-form'; import KeymapsForm from './form/keymaps-form'; import BlacklistForm from './form/blacklist-form'; import * as settingActions from 'settings/actions/setting'; @@ -49,7 +49,7 @@ class SettingsComponent extends Component {
Search Engines - this.bindForm('search', value)} /> -- cgit v1.2.3 From 0967304ebe713bc24078b20ac3a710fd42f2f611 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 12:18:12 +0900 Subject: add SearchForm test --- src/settings/components/form/search-form.jsx | 18 ++-- .../components/form/search-engine-form.test.jsx | 104 +++++++++++++++++++++ 2 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 test/settings/components/form/search-engine-form.test.jsx (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx index 9bafb8d..98b0655 100644 --- a/src/settings/components/form/search-form.jsx +++ b/src/settings/components/form/search-form.jsx @@ -10,10 +10,9 @@ class SearchForm extends Component { if (!value) { value = { default: '', engines: []}; } - let { - default: defaultEngine, - engines - } = value; + if (!value.engines) { + value.engines = []; + } return
@@ -22,7 +21,7 @@ class SearchForm extends Component {
Default
{ - engines.map((engine, index) => { + value.engines.map((engine, index) => { return
@@ -50,12 +49,17 @@ class SearchForm extends Component { return; } + let value = this.props.value; let name = e.target.name; let index = e.target.getAttribute('data-index'); - let next = Object.assign({}, this.props.value); + let next = Object.assign({}, { + default: value.default, + engines: value.engines ? value.engines.slice() : [], + }); if (name === 'name') { next.engines[index][0] = e.target.value; + next.default = this.props.value.engines[index][0]; } else if (name === 'url') { next.engines[index][1] = e.target.value; } else if (name === 'default') { diff --git a/test/settings/components/form/search-engine-form.test.jsx b/test/settings/components/form/search-engine-form.test.jsx new file mode 100644 index 0000000..9600cae --- /dev/null +++ b/test/settings/components/form/search-engine-form.test.jsx @@ -0,0 +1,104 @@ +import { expect } from 'chai'; +import { h, render } from 'preact'; +import SearchForm from 'settings/components/form/search-form' + +describe("settings/form/SearchForm", () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + describe('render', () => { + it('renders SearchForm', () => { + render(, document.body); + + let names = document.querySelectorAll('input[name=name]'); + expect(names).to.have.lengthOf(2); + expect(names[0].value).to.equal('google'); + expect(names[1].value).to.equal('yahoo'); + + let urls = document.querySelectorAll('input[name=url]'); + expect(urls).to.have.lengthOf(2); + expect(urls[0].value).to.equal('google.com'); + expect(urls[1].value).to.equal('yahoo.com'); + }); + + it('renders blank value', () => { + render(, document.body); + + let names = document.querySelectorAll('input[name=name]'); + let urls = document.querySelectorAll('input[name=url]'); + expect(names).to.have.lengthOf(0); + expect(urls).to.have.lengthOf(0); + }); + + it('renders blank engines', () => { + render(, document.body); + + let names = document.querySelectorAll('input[name=name]'); + let urls = document.querySelectorAll('input[name=url]'); + expect(names).to.have.lengthOf(0); + expect(urls).to.have.lengthOf(0); + }); + }); + + describe('onChange event', () => { + it('invokes onChange event on edit', (done) => { + render( { + expect(value.default).to.equal('louvre'); + expect(value.engines).to.have.lengthOf(2) + .and.have.deep.members([['louvre', 'google.com'], ['yahoo', 'yahoo.com']]) + + done(); + }} />, document.body); + + let radio = document.querySelectorAll('input[type=radio]'); + radio.checked = true; + + let name = document.querySelector('input[name=name]'); + name.value = 'louvre'; + name.dispatchEvent(new Event('change')) + }); + + it('invokes onChange event on delete', (done) => { + render( { + expect(value.default).to.equal('yahoo'); + expect(value.engines).to.have.lengthOf(1) + .and.have.deep.members([['yahoo', 'yahoo.com']]) + + done(); + }} />, document.body); + + let button = document.querySelector('input[type=button]'); + button.click(); + }); + + it('invokes onChange event on add', (done) => { + render( { + expect(value.default).to.equal('yahoo'); + expect(value.engines).to.have.lengthOf(2) + .and.have.deep.members([['google', 'google.com'], ['', '']]) + + done(); + }} />, document.body); + + let button = document.querySelector('input[type=button].ui-add-button'); + button.click(); + }); + }); +}); -- cgit v1.2.3 From 705c47bc6379a8d1fea4f775a6af98c97d4eab81 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 12:34:49 +0900 Subject: add KeymapsForm test --- src/settings/components/form/keymaps-form.jsx | 6 ++- .../settings/components/form/keymaps-form.test.jsx | 53 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/settings/components/form/keymaps-form.test.jsx (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index 8e93c3f..f64320c 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -58,6 +58,10 @@ const KeyMapFields = [ class KeymapsForm extends Component { render() { + let values = this.props.value; + if (!values) { + values = {}; + } return
{ KeyMapFields.map((group, index) => { @@ -66,7 +70,7 @@ class KeymapsForm extends Component { group.map((field) => { let name = field[0]; let label = field[1]; - let value = this.props.value[name]; + let value = values[name]; return { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + describe('render', () => { + it('renders KeymapsForm', () => { + render(, document.body); + + let inputj = document.getElementById('scroll.vertically?{"count":1}'); + let inputk = document.getElementById('scroll.vertically?{"count":-1}'); + + expect(inputj.value).to.equal('j'); + expect(inputk.value).to.equal('k'); + }); + + it('renders blank value', () => { + render(, document.body); + + let inputj = document.getElementById('scroll.vertically?{"count":1}'); + let inputk = document.getElementById('scroll.vertically?{"count":-1}'); + + expect(inputj.value).to.be.empty; + expect(inputk.value).to.be.empty; + }); + }); + + describe('onChange event', () => { + it('invokes onChange event on edit', (done) => { + render( { + expect(value['scroll.vertically?{"count":1}']).to.equal('jjj'); + + done(); + }} />, document.body); + + let input = document.getElementById('scroll.vertically?{"count":1}'); + input.value = 'jjj'; + input.dispatchEvent(new Event('change')) + }); + }); +}); -- cgit v1.2.3 From 26777d9e309dbc328b59581adb92f160c18f812c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 16:41:34 +0900 Subject: fix form css --- src/settings/components/form/blacklist-form.jsx | 3 ++- src/settings/components/form/keymaps-form.scss | 2 +- src/settings/components/form/search-form.jsx | 3 ++- src/settings/components/form/search-form.scss | 2 ++ src/settings/components/site.scss | 2 +- src/settings/components/ui/add-button.jsx | 2 +- src/settings/components/ui/add-button.scss | 12 +++++++++++- src/settings/components/ui/delete-button.scss | 1 + src/settings/components/ui/input.scss | 3 ++- 9 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/blacklist-form.jsx b/src/settings/components/form/blacklist-form.jsx index 4333929..7ae9652 100644 --- a/src/settings/components/form/blacklist-form.jsx +++ b/src/settings/components/form/blacklist-form.jsx @@ -23,7 +23,8 @@ class BlacklistForm extends Component {
; }) } - +
; } diff --git a/src/settings/components/form/keymaps-form.scss b/src/settings/components/form/keymaps-form.scss index 8b86c80..3a83910 100644 --- a/src/settings/components/form/keymaps-form.scss +++ b/src/settings/components/form/keymaps-form.scss @@ -1,5 +1,5 @@ .form-keymaps-form { - column-count: 2; + column-count: 3; .keymap-fields-group { margin-top: 24px; } diff --git a/src/settings/components/form/search-form.jsx b/src/settings/components/form/search-form.jsx index 98b0655..e85761f 100644 --- a/src/settings/components/form/search-form.jsx +++ b/src/settings/components/form/search-form.jsx @@ -40,7 +40,8 @@ class SearchForm extends Component {
; }) } - +
; } diff --git a/src/settings/components/form/search-form.scss b/src/settings/components/form/search-form.scss index 8814ef5..26b2f44 100644 --- a/src/settings/components/form/search-form.scss +++ b/src/settings/components/form/search-form.scss @@ -4,9 +4,11 @@ .column-name { flex: 1; + min-width: 0; } .column-url { flex: 5; + min-width: 0; } .column-option { text-align: right; diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss index c8dd422..c0c4f9e 100644 --- a/src/settings/components/site.scss +++ b/src/settings/components/site.scss @@ -20,7 +20,7 @@ legend { font-size: 1.5rem; - line-height: 1.5rem; + padding: .5rem 0; font-weight: bold; } } diff --git a/src/settings/components/ui/add-button.jsx b/src/settings/components/ui/add-button.jsx index c8d8856..79292d8 100644 --- a/src/settings/components/ui/add-button.jsx +++ b/src/settings/components/ui/add-button.jsx @@ -4,7 +4,7 @@ import { h, Component } from 'preact'; class AddButton extends Component { render() { return ; } } diff --git a/src/settings/components/ui/add-button.scss b/src/settings/components/ui/add-button.scss index 1c893ae..beb5688 100644 --- a/src/settings/components/ui/add-button.scss +++ b/src/settings/components/ui/add-button.scss @@ -1,3 +1,13 @@ .ui-add-button { - font-size: 80% + border: none; + padding: 4; + display: inline; + background: none; + font-weight: bold; + color: green; + cursor: pointer; + + &:hover { + color: darkgreen; + } } diff --git a/src/settings/components/ui/delete-button.scss b/src/settings/components/ui/delete-button.scss index 7aa2f39..5932a72 100644 --- a/src/settings/components/ui/delete-button.scss +++ b/src/settings/components/ui/delete-button.scss @@ -5,6 +5,7 @@ display: inline; background: none; color: red; + cursor: pointer; &:hover { color: darkred; diff --git a/src/settings/components/ui/input.scss b/src/settings/components/ui/input.scss index 92df712..ad4daf8 100644 --- a/src/settings/components/ui/input.scss +++ b/src/settings/components/ui/input.scss @@ -11,8 +11,9 @@ display: inline-block; } - input { + input[type='text'] { padding: 4px; + width: 8rem; } input.input-crror, -- cgit v1.2.3 From 8c79b2c5e7e3b25ce5eb0fa94e856b5b9b1f77f1 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 21:06:39 +0900 Subject: fix keymap field --- src/settings/components/form/keymaps-form.jsx | 4 ++-- src/settings/components/form/keymaps-form.scss | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index f64320c..8ec0456 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -62,10 +62,10 @@ class KeymapsForm extends Component { if (!values) { values = {}; } - return
+ return
{ KeyMapFields.map((group, index) => { - return
+ return
{ group.map((field) => { let name = field[0]; diff --git a/src/settings/components/form/keymaps-form.scss b/src/settings/components/form/keymaps-form.scss index 3a83910..1a4e5cd 100644 --- a/src/settings/components/form/keymaps-form.scss +++ b/src/settings/components/form/keymaps-form.scss @@ -1,9 +1,11 @@ .form-keymaps-form { column-count: 3; - .keymap-fields-group { + + &-field-group { margin-top: 24px; } - .keymap-fields-group:first-of-type { - margin-top: 0; + + &-field-group:first-of-type { + margin-top: 24px; } } -- cgit v1.2.3 From 6b7fad3e494ddca1133fd9e9e6c7ebe7479b7f03 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 21:54:27 +0900 Subject: fix form key bindings --- src/settings/components/form/keymaps-form.jsx | 6 ++++-- src/shared/settings/default.js | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index 8ec0456..ac24689 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -8,8 +8,10 @@ const KeyMapFields = [ ['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.home', 'Scroll to leftmost'], + ['scroll.end', 'Scroll to rightmost'], + ['scroll.top', 'Scroll to top'], + ['scroll.bottom', 'Scroll to bottom'], ['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'], diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index 71465c9..527725a 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -70,6 +70,8 @@ export default { 'scroll.horizonally?{"count":1}': 'l', 'scroll.home': '0', 'scroll.end': '$', + 'scroll.top': 'gg', + 'scroll.bottom': 'G', 'scroll.pages?{"count":-0.5}': '', 'scroll.pages?{"count":0.5}': '', 'scroll.pages?{"count":-1}': '', -- cgit v1.2.3 From 6821372fc71779b458eed52f614d5a15571129d0 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 26 Nov 2017 21:59:29 +0900 Subject: fix form key bindings --- src/settings/components/form/keymaps-form.jsx | 3 ++- src/shared/settings/default.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index ac24689..f99318f 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -23,7 +23,8 @@ const KeyMapFields = [ ['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.reload?{"cache":false}', 'Reload current tab'], + ['tabs.reload?{"cache":true}', 'Reload with no caches'], ['tabs.pin.toggle', 'Toggle pinned state'], ['tabs.duplicate', 'Dupplicate a tab'], ], [ diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index 527725a..14ed548 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -83,7 +83,8 @@ export default { 'tabs.prev?{"count":1}': 'K', 'tabs.first': 'g0', 'tabs.last': 'g$', - 'tabs.reload?{"cache":true}': 'r', + 'tabs.reload?{"cache":false}': 'r', + 'tabs.reload?{"cache":true}': 'R', 'tabs.pin.toggle': 'zp', 'tabs.duplicate': 'zd', -- cgit v1.2.3 From e1060f9bb218202d13a4382584f220d47173194c Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Tue, 28 Nov 2017 20:45:22 +0900 Subject: remove default form settings --- src/settings/components/form/keymaps-form.jsx | 4 ++ src/settings/components/index.jsx | 15 +++++- src/shared/settings/default.js | 68 --------------------------- src/shared/settings/values.js | 14 +++--- test/shared/settings/values.test.js | 4 +- 5 files changed, 27 insertions(+), 78 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index f99318f..f3b6abe 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -58,6 +58,8 @@ const KeyMapFields = [ ] ]; +const AllowdOps = [].concat(...KeyMapFields.map(group => group.map(e => e[0]))); + class KeymapsForm extends Component { render() { @@ -99,4 +101,6 @@ class KeymapsForm extends Component { } } +KeymapsForm.AllowdOps = AllowdOps; + export default KeymapsForm; diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index 3961982..38f7db8 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -123,6 +123,18 @@ class SettingsComponent extends Component { } } + validateValue(e) { + let next = Object.assign({}, this.state); + + next.errors.json = ''; + try { + this.validate(e.target); + } catch (err) { + next.errors.json = err.message; + } + next.settings[e.target.name] = e.target.value; + } + bindForm(name, value) { let next = Object.assign({}, this.state, { settings: Object.assign({}, this.state.settings, { @@ -164,7 +176,8 @@ class SettingsComponent extends Component { return; } next.settings.form = - settingsValues.formFromJson(this.state.settings.json); + settingsValues.formFromJson( + this.state.settings.json, KeymapsForm.AllowdOps); } next.settings.source = to; diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index 14ed548..d187565 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -61,72 +61,4 @@ export default { } } }`, - - 'form': { - 'keymaps': { - 'scroll.vertically?{"count":1}': 'j', - 'scroll.vertically?{"count":-1}': 'k', - 'scroll.horizonally?{"count":-1}': 'h', - 'scroll.horizonally?{"count":1}': 'l', - 'scroll.home': '0', - 'scroll.end': '$', - 'scroll.top': 'gg', - 'scroll.bottom': 'G', - 'scroll.pages?{"count":-0.5}': '', - 'scroll.pages?{"count":0.5}': '', - 'scroll.pages?{"count":-1}': '', - 'scroll.pages?{"count":1}': '', - - 'tabs.close': 'd', - 'tabs.reopen': 'u', - 'tabs.next?{"count":1}': 'J', - 'tabs.prev?{"count":1}': 'K', - 'tabs.first': 'g0', - 'tabs.last': 'g$', - 'tabs.reload?{"cache":false}': 'r', - 'tabs.reload?{"cache":true}': 'R', - 'tabs.pin.toggle': 'zp', - 'tabs.duplicate': 'zd', - - 'follow.start?{"newTab":false}': 'f', - 'follow.start?{"newTab":true}': 'F', - 'navigate.history.prev': 'H', - 'navigate.history.next': 'L', - 'navigate.link.next': ']]', - 'navigate.link.prev': '[[', - 'navigate.parent': 'gu', - 'navigate.root': 'gU', - - 'find.start': '/', - 'find.next': 'n', - 'find.prev': 'N', - - 'command.show': ':', - 'command.show.open?{"alter":false}': 'o', - 'command.show.open?{"alter":true}': 'O', - 'command.show.tabopen?{"alter":false}': 't', - 'command.show.tabopen?{"alter":true}': 'T', - 'command.show.winopen?{"alter":false}': 'w', - 'command.show.winopen?{"alter":true}': 'W', - 'command.show.buffer': 'b', - - 'addon.toggle.enabled': '', - 'urls.yank': 'y', - 'zoom.in': 'zi', - 'zoom.out': 'zo', - 'zoom.neutral': 'zz', - }, - 'search': { - 'default': 'google', - 'engines': [ - ['google', 'https,//google.com/search?q={}'], - ['yahoo', 'https,//search.yahoo.com/search?p={}'], - ['bing', 'https,//www.bing.com/search?q={}'], - ['duckduckgo', 'https,//duckduckgo.com/?q={}'], - ['twitter', 'https,//twitter.com/search?q={}'], - ['wikipedia', 'https,//en.wikipedia.org/w/index.php?search={}'], - ] - }, - 'blacklist': [], - } }; diff --git a/src/shared/settings/values.js b/src/shared/settings/values.js index 4482fbb..4e55fa0 100644 --- a/src/shared/settings/values.js +++ b/src/shared/settings/values.js @@ -1,5 +1,3 @@ -import DefaultSettings from './default'; - const operationFromFormName = (name) => { let [type, argStr] = name.split('?'); let args = {}; @@ -55,16 +53,16 @@ const jsonFromValue = (value) => { return JSON.stringify(value, undefined, 2); }; -const formFromValue = (value) => { - +const formFromValue = (value, allowedOps) => { let keymaps = undefined; + if (value.keymaps) { - let allowedOps = new Set(Object.keys(DefaultSettings.form.keymaps)); + let allowedSet = new Set(allowedOps); keymaps = {}; for (let keys of Object.keys(value.keymaps)) { let op = operationToFormName(value.keymaps[keys]); - if (allowedOps.has(op)) { + if (allowedSet.has(op)) { keymaps[op] = keys; } } @@ -89,9 +87,9 @@ const jsonFromForm = (form) => { return jsonFromValue(valueFromForm(form)); }; -const formFromJson = (json) => { +const formFromJson = (json, allowedOps) => { let value = valueFromJson(json); - return formFromValue(value); + return formFromValue(value, allowedOps); }; export { diff --git a/test/shared/settings/values.test.js b/test/shared/settings/values.test.js index 2c222b6..2632cd7 100644 --- a/test/shared/settings/values.test.js +++ b/test/shared/settings/values.test.js @@ -98,9 +98,11 @@ describe("settings values", () => { search: { default: 'google', engines: { google: 'https://google.com/search?q={}' }}, blacklist: [ '*.slack.com'] }; - let form = values.formFromValue(value); + let allowed = ['scroll.vertically?{"count":1}', 'scroll.home' ]; + let form = values.formFromValue(value, allowed); expect(form.keymaps).to.have.property('scroll.vertically?{"count":1}', 'j'); + expect(form.keymaps).to.not.have.property('scroll.vertically?{"count":100}'); expect(form.keymaps).to.have.property('scroll.home', '0'); expect(Object.keys(form.keymaps)).to.have.lengthOf(2); expect(form.search).to.have.property('default', 'google'); -- cgit v1.2.3 From 2e67d9a667385acf2780fde417e8490a5dc5eb92 Mon Sep 17 00:00:00 2001 From: l4 Date: Thu, 28 Dec 2017 13:58:53 +0700 Subject: fix scroll settings typos --- src/settings/components/form/keymaps-form.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index f3b6abe..c399570 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -13,9 +13,9 @@ const KeyMapFields = [ ['scroll.top', 'Scroll to top'], ['scroll.bottom', 'Scroll to bottom'], ['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":0.5}', 'Scroll down by half of screen'], ['scroll.pages?{"count":-1}', 'Scroll up by a screen'], - ['scroll.pages?{"count":1}', 'Scroll up by a screen'], + ['scroll.pages?{"count":1}', 'Scroll down by a screen'], ], [ ['tabs.close', 'Close a tab'], ['tabs.reopen', 'Reopen closed tab'], -- cgit v1.2.3 From 54a7662cd1e7372910e9ce81aae1a904f3b26c82 Mon Sep 17 00:00:00 2001 From: usk Date: Wed, 3 Jan 2018 07:19:25 +0900 Subject: open clipboard's URL in current/new tab --- QA.md | 2 ++ README.md | 2 ++ manifest.json | 3 ++- src/content/actions/operation.js | 2 ++ src/content/urls.js | 26 +++++++++++++++++++++++++- src/settings/components/form/keymaps-form.jsx | 2 ++ src/shared/operations.js | 3 ++- src/shared/settings/default.js | 2 ++ 8 files changed, 39 insertions(+), 3 deletions(-) (limited to 'src/settings/components/form') diff --git a/QA.md b/QA.md index 1a0839e..1c06861 100644 --- a/QA.md +++ b/QA.md @@ -46,6 +46,8 @@ The behaviors of the console are tested in [Console section](#consoles). - [ ] zi, zo: zoom-in and zoom-out - [ ] zz: set zoom level as default - [ ] y: yank current URL and show a message +- [ ] p: open clipbord's URL in current tab +- [ ] P: open clipbord's URL in new tab - [ ] Toggle enabled/disabled of plugin bu Shift+Esc ### Following links diff --git a/README.md b/README.md index fdc48d4..a249ada 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ The default mappings are as follows: - zi, zo: zoom-in/zoom-out - zz: Set default zoom level - y: copy URL in current tab +- p: open clipbord's URL in current tab +- P: open clipbord's URL in new tab - Shift+Esc: enable or disable the add-on in current tab. ### Console commands diff --git a/manifest.json b/manifest.json index 78479c2..02d8589 100644 --- a/manifest.json +++ b/manifest.json @@ -30,7 +30,8 @@ "history", "sessions", "storage", - "tabs" + "tabs", + "clipboardRead" ], "web_accessible_resources": [ "build/console.html", diff --git a/src/content/actions/operation.js b/src/content/actions/operation.js index 767f14b..0a5cd97 100644 --- a/src/content/actions/operation.js +++ b/src/content/actions/operation.js @@ -60,6 +60,8 @@ const exec = (operation) => { type: messages.CONSOLE_SHOW_INFO, text: 'Current url yanked', }); + case operations.URLS_PASTE: + return urls.paste(window, operation.newTab ? operation.newTab : false); default: browser.runtime.sendMessage({ type: messages.BACKGROUND_OPERATION, diff --git a/src/content/urls.js b/src/content/urls.js index 8f8a1ac..9b7b284 100644 --- a/src/content/urls.js +++ b/src/content/urls.js @@ -1,3 +1,5 @@ +import messages from 'shared/messages'; + const yank = (win) => { let input = win.document.createElement('input'); win.document.body.append(input); @@ -12,4 +14,26 @@ const yank = (win) => { input.remove(); }; -export { yank }; +const paste = (win, newTab) => { + let textarea = win.document.createElement('textarea'); + win.document.body.append(textarea); + + textarea.style.position = 'fixed'; + textarea.style.top = '-100px'; + textarea.contentEditable = 'true'; + textarea.focus(); + + if (win.document.execCommand('paste')) { + if (/^(https?|ftp):\/\//.test(textarea.textContent)) { + browser.runtime.sendMessage({ + type: messages.OPEN_URL, + url: textarea.textContent, + newTab: newTab ? newTab : false, + }); + } + } + + textarea.remove(); +}; + +export { yank, paste }; diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index c399570..eb77e52 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -52,6 +52,8 @@ const KeyMapFields = [ ], [ ['addon.toggle.enabled', 'Enable or disable'], ['urls.yank', 'Copy current URL'], + ['urls.paste?{"newTab":false}', 'Open clipboard\'s URL in current tab'], + ['urls.paste?{"newTab":true}', 'Open clipboard\'s URL in new tab'], ['zoom.in', 'Zoom-in'], ['zoom.out', 'Zoom-out'], ['zoom.neutral', 'Reset zoom level'], diff --git a/src/shared/operations.js b/src/shared/operations.js index 4c221ba..7334369 100644 --- a/src/shared/operations.js +++ b/src/shared/operations.js @@ -49,8 +49,9 @@ export default { ZOOM_OUT: 'zoom.out', ZOOM_NEUTRAL: 'zoom.neutral', - // Url yank + // Url yank/paste URLS_YANK: 'urls.yank', + URLS_PASTE: 'urls.paste', // Find FIND_START: 'find.start', diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index d187565..6b71717 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -44,6 +44,8 @@ export default { "gu": { "type": "navigate.parent" }, "gU": { "type": "navigate.root" }, "y": { "type": "urls.yank" }, + "p": { "type": "urls.paste", "newTab": false }, + "P": { "type": "urls.paste", "newTab": true }, "/": { "type": "find.start" }, "n": { "type": "find.next" }, "N": { "type": "find.prev" }, -- cgit v1.2.3 From 86df54067f8a105264a6816e115fd65efa75fb5b Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Fri, 5 Jan 2018 22:54:36 +0900 Subject: Add PropertiesForm --- src/settings/components/form/properties-form.jsx | 60 +++++++++++++++ src/settings/components/form/properties-form.scss | 12 +++ src/settings/components/index.jsx | 10 +++ .../components/form/properties-form.test.jsx | 86 ++++++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 src/settings/components/form/properties-form.jsx create mode 100644 src/settings/components/form/properties-form.scss create mode 100644 test/settings/components/form/properties-form.test.jsx (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/properties-form.jsx b/src/settings/components/form/properties-form.jsx new file mode 100644 index 0000000..55c8512 --- /dev/null +++ b/src/settings/components/form/properties-form.jsx @@ -0,0 +1,60 @@ +import './properties-form.scss'; +import { h, Component } from 'preact'; + +class PropertiesForm extends Component { + + render() { + let types = this.props.types; + let value = this.props.value; + if (!value) { + value = {}; + } + + return
+ { + Object.keys(types).map((name) => { + let type = types[name]; + let inputType = null; + if (type === 'string') { + inputType = 'text'; + } else if (type === 'number') { + inputType = 'number'; + } else if (type === 'boolean') { + inputType = 'checkbox'; + } + return
+ +
; + }) + } +
; + } + + bindValue(e) { + if (!this.props.onChange) { + return; + } + + let name = e.target.name; + let next = Object.assign({}, this.props.value); + if (e.target.type.toLowerCase() === 'checkbox') { + next[name] = e.target.checked; + } else if (e.target.type.toLowerCase() === 'number') { + next[name] = Number(e.target.value); + } else { + next[name] = e.target.value; + } + + this.props.onChange(next); + } +} + +export default PropertiesForm; diff --git a/src/settings/components/form/properties-form.scss b/src/settings/components/form/properties-form.scss new file mode 100644 index 0000000..7c9e167 --- /dev/null +++ b/src/settings/components/form/properties-form.scss @@ -0,0 +1,12 @@ +.form-properties-form { + &-row { + .column-name { + display: inline-block; + min-width: 5rem; + font-weight: bold; + } + .column-input { + line-height: 2.2rem; + } + } +} diff --git a/src/settings/components/index.jsx b/src/settings/components/index.jsx index 074c4c7..c41aa6b 100644 --- a/src/settings/components/index.jsx +++ b/src/settings/components/index.jsx @@ -4,6 +4,8 @@ import Input from './ui/input'; import SearchForm from './form/search-form'; import KeymapsForm from './form/keymaps-form'; import BlacklistForm from './form/blacklist-form'; +import PropertiesForm from './form/properties-form'; +import PropertyTypes from 'shared/settings/property-types'; import * as settingActions from 'settings/actions/setting'; import * as validator from 'shared/settings/validator'; import * as settingsValues from 'shared/settings/values'; @@ -65,6 +67,14 @@ class SettingsComponent extends Component { onChange={value => this.bindForm('blacklist', value)} />
+
+ Properties + this.bindForm('properties', value)} + /> +
; } diff --git a/test/settings/components/form/properties-form.test.jsx b/test/settings/components/form/properties-form.test.jsx new file mode 100644 index 0000000..4807361 --- /dev/null +++ b/test/settings/components/form/properties-form.test.jsx @@ -0,0 +1,86 @@ +import { expect } from 'chai'; +import { h, render } from 'preact'; +import PropertiesForm from 'settings/components/form/properties-form' + +describe("settings/form/PropertiesForm", () => { + beforeEach(() => { + document.body.innerHTML = ''; + }); + + describe('render', () => { + it('renders PropertiesForm', () => { + let types = { + mystr: 'string', + mynum: 'number', + mybool: 'boolean', + empty: 'string', + } + let value = { + mystr: 'abc', + mynum: 123, + mybool: true, + }; + render(, document.body); + + let strInput = document.querySelector('input[name=mystr]'); + let numInput = document.querySelector('input[name=mynum]'); + let boolInput = document.querySelector('input[name=mybool]'); + let emptyInput = document.querySelector('input[name=empty]'); + + expect(strInput.type).to.equals('text'); + expect(strInput.value).to.equal('abc'); + expect(numInput.type).to.equals('number'); + expect(numInput.value).to.equal('123'); + expect(boolInput.type).to.equals('checkbox'); + expect(boolInput.checked).to.be.true; + expect(emptyInput.type).to.equals('text'); + expect(emptyInput.value).to.be.empty; + }); + }); + + describe('onChange', () => { + it('invokes onChange event on text changed', (done) => { + render( { + expect(value).to.have.property('myvalue', 'abcd'); + done(); + }} + />, document.body); + + let input = document.querySelector('input[name=myvalue]'); + input.value = 'abcd' + input.dispatchEvent(new Event('change')) + }); + + it('invokes onChange event on number changeed', (done) => { + render( { + expect(value).to.have.property('myvalue', 1234); + done(); + }} + />, document.body); + + let input = document.querySelector('input[name=myvalue]'); + input.value = '1234' + input.dispatchEvent(new Event('change')) + }); + + it('invokes onChange event on checkbox changed', (done) => { + render( { + expect(value).to.have.property('myvalue', true); + done(); + }} + />, document.body); + + let input = document.querySelector('input[name=myvalue]'); + input.click(); + }); + }); +}); -- cgit v1.2.3 From e3fdf742e7dc3fa3518746d185418a2e63ca2118 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sat, 13 Jan 2018 22:42:39 +0900 Subject: add focus input key map --- src/settings/components/form/keymaps-form.jsx | 1 + src/shared/settings/default.js | 1 + 2 files changed, 2 insertions(+) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index eb77e52..e25107c 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -36,6 +36,7 @@ const KeyMapFields = [ ['navigate.link.prev', 'Open previous link'], ['navigate.parent', 'Go to parent directory'], ['navigate.root', 'Go to root directory'], + ['focus.input', 'Focus input'], ], [ ['find.start', 'Start find mode'], ['find.next', 'Find next word'], diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index 0c3f0d9..4ad81c4 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -43,6 +43,7 @@ export default { "]]": { "type": "navigate.link.next" }, "gu": { "type": "navigate.parent" }, "gU": { "type": "navigate.root" }, + "gi": { "type": "focus.input" }, "y": { "type": "urls.yank" }, "p": { "type": "urls.paste", "newTab": false }, "P": { "type": "urls.paste", "newTab": true }, -- cgit v1.2.3 From f55f0bfd98c9d6f3c41c8601e48ac9c73c5c0d38 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 15 Jan 2018 15:18:56 -0500 Subject: keymaps-form: fix a typo --- src/settings/components/form/keymaps-form.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/settings/components/form') diff --git a/src/settings/components/form/keymaps-form.jsx b/src/settings/components/form/keymaps-form.jsx index eb77e52..4e08616 100644 --- a/src/settings/components/form/keymaps-form.jsx +++ b/src/settings/components/form/keymaps-form.jsx @@ -26,7 +26,7 @@ const KeyMapFields = [ ['tabs.reload?{"cache":false}', 'Reload current tab'], ['tabs.reload?{"cache":true}', 'Reload with no caches'], ['tabs.pin.toggle', 'Toggle pinned state'], - ['tabs.duplicate', 'Dupplicate a tab'], + ['tabs.duplicate', 'Duplicate a tab'], ], [ ['follow.start?{"newTab":false}', 'Follow a link'], ['follow.start?{"newTab":true}', 'Follow a link in new tab'], -- cgit v1.2.3