aboutsummaryrefslogtreecommitdiff
path: root/src/settings
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2020-05-02 17:25:56 +0900
committerGitHub <noreply@github.com>2020-05-02 17:25:56 +0900
commit5df0537bcf65a341e79852b1b30379c73318529c (patch)
treeaee5efe52412855f620cb514a13a2c14373f27b7 /src/settings
parent685f2b7b69218b06b5bb676069e35f79c5048c9b (diff)
parent75abd90ecb8201ad845b266f96220d8adfe19b2d (diff)
Merge pull request #749 from ueokande/qa-0.28
QA 0.28
Diffstat (limited to 'src/settings')
-rw-r--r--src/settings/actions/index.ts24
-rw-r--r--src/settings/actions/setting.ts39
-rw-r--r--src/settings/components/form/BlacklistForm.tsx71
-rw-r--r--src/settings/components/form/KeymapsForm.tsx54
-rw-r--r--src/settings/components/form/PartialBlacklistForm.tsx100
-rw-r--r--src/settings/components/form/PropertiesForm.tsx66
-rw-r--r--src/settings/components/form/SearchForm.tsx112
-rw-r--r--src/settings/components/index.tsx222
-rw-r--r--src/settings/components/ui/AddButton.tsx15
-rw-r--r--src/settings/components/ui/DeleteButton.tsx15
-rw-r--r--src/settings/components/ui/Input.tsx89
-rw-r--r--src/settings/index.tsx23
-rw-r--r--src/settings/keymaps.ts137
-rw-r--r--src/settings/reducers/setting.ts64
-rw-r--r--src/settings/storage.ts16
15 files changed, 579 insertions, 468 deletions
diff --git a/src/settings/actions/index.ts b/src/settings/actions/index.ts
index dfa41c4..6b06ef8 100644
--- a/src/settings/actions/index.ts
+++ b/src/settings/actions/index.ts
@@ -1,12 +1,14 @@
import {
- JSONTextSettings, FormSettings, SettingSource,
-} from '../../shared/SettingData';
+ JSONTextSettings,
+ FormSettings,
+ SettingSource,
+} from "../../shared/SettingData";
// Settings
-export const SETTING_SET_SETTINGS = 'setting.set.settings';
-export const SETTING_SHOW_ERROR = 'setting.show.error';
-export const SETTING_SWITCH_TO_FORM = 'setting.switch.to.form';
-export const SETTING_SWITCH_TO_JSON = 'setting.switch.to.json';
+export const SETTING_SET_SETTINGS = "setting.set.settings";
+export const SETTING_SHOW_ERROR = "setting.show.error";
+export const SETTING_SWITCH_TO_FORM = "setting.switch.to.form";
+export const SETTING_SWITCH_TO_JSON = "setting.switch.to.json";
interface SettingSetSettingsAcion {
type: typeof SETTING_SET_SETTINGS;
@@ -23,14 +25,16 @@ interface SettingShowErrorAction {
interface SettingSwitchToFormAction {
type: typeof SETTING_SWITCH_TO_FORM;
- form: FormSettings,
+ form: FormSettings;
}
interface SettingSwitchToJsonAction {
type: typeof SETTING_SWITCH_TO_JSON;
- json: JSONTextSettings,
+ json: JSONTextSettings;
}
export type SettingAction =
- SettingSetSettingsAcion | SettingShowErrorAction |
- SettingSwitchToFormAction | SettingSwitchToJsonAction;
+ | SettingSetSettingsAcion
+ | SettingShowErrorAction
+ | SettingSwitchToFormAction
+ | SettingSwitchToJsonAction;
diff --git a/src/settings/actions/setting.ts b/src/settings/actions/setting.ts
index 93ca5f8..e880ae4 100644
--- a/src/settings/actions/setting.ts
+++ b/src/settings/actions/setting.ts
@@ -1,15 +1,17 @@
-import * as actions from './index';
-import * as storages from '../storage';
+import * as actions from "./index";
+import * as storages from "../storage";
import SettingData, {
- JSONTextSettings, FormSettings, SettingSource,
-} from '../../shared/SettingData';
+ JSONTextSettings,
+ FormSettings,
+ SettingSource,
+} from "../../shared/SettingData";
-const load = async(): Promise<actions.SettingAction> => {
+const load = async (): Promise<actions.SettingAction> => {
const data = await storages.load();
return set(data);
};
-const save = async(data: SettingData): Promise<actions.SettingAction> => {
+const save = async (data: SettingData): Promise<actions.SettingAction> => {
try {
if (data.getSource() === SettingSource.JSON) {
// toSettings exercise validation
@@ -26,7 +28,6 @@ const save = async(data: SettingData): Promise<actions.SettingAction> => {
return set(data);
};
-
const switchToForm = (json: JSONTextSettings): actions.SettingAction => {
try {
// toSettings exercise validation
@@ -55,18 +56,18 @@ const switchToJson = (form: FormSettings): actions.SettingAction => {
const set = (data: SettingData): actions.SettingAction => {
const source = data.getSource();
switch (source) {
- case SettingSource.JSON:
- return {
- type: actions.SETTING_SET_SETTINGS,
- source: source,
- json: data.getJSON(),
- };
- case SettingSource.Form:
- return {
- type: actions.SETTING_SET_SETTINGS,
- source: source,
- form: data.getForm(),
- };
+ case SettingSource.JSON:
+ return {
+ type: actions.SETTING_SET_SETTINGS,
+ source: source,
+ json: data.getJSON(),
+ };
+ case SettingSource.Form:
+ return {
+ type: actions.SETTING_SET_SETTINGS,
+ source: source,
+ form: data.getForm(),
+ };
}
throw new Error(`unknown source: ${source}`);
};
diff --git a/src/settings/components/form/BlacklistForm.tsx b/src/settings/components/form/BlacklistForm.tsx
index 51c32f4..859cb9f 100644
--- a/src/settings/components/form/BlacklistForm.tsx
+++ b/src/settings/components/form/BlacklistForm.tsx
@@ -1,8 +1,8 @@
-import './BlacklistForm.scss';
-import AddButton from '../ui/AddButton';
-import DeleteButton from '../ui/DeleteButton';
-import React from 'react';
-import Blacklist, { BlacklistItem } from '../../../shared/settings/Blacklist';
+import "./BlacklistForm.scss";
+import AddButton from "../ui/AddButton";
+import DeleteButton from "../ui/DeleteButton";
+import React from "react";
+import Blacklist, { BlacklistItem } from "../../../shared/settings/Blacklist";
interface Props {
value: Blacklist;
@@ -18,45 +18,56 @@ class BlacklistForm extends React.Component<Props> {
};
render() {
- return <div className='form-blacklist-form'>
- {
- this.props.value.items.map((item, index) => {
+ return (
+ <div className="form-blacklist-form">
+ {this.props.value.items.map((item, index) => {
if (item.partial) {
return null;
}
- return <div key={index} className='form-blacklist-form-row'>
- <input data-index={index} type='text' name='url'
- className='column-url' value={item.pattern}
- onChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- <DeleteButton data-index={index} name='delete'
- onClick={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- </div>;
- })
- }
- <AddButton name='add' style={{ float: 'right' }}
- onClick={this.bindValue.bind(this)} />
- </div>;
+ return (
+ <div key={index} className="form-blacklist-form-row">
+ <input
+ data-index={index}
+ type="text"
+ name="url"
+ className="column-url"
+ value={item.pattern}
+ onChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ <DeleteButton
+ data-index={index}
+ name="delete"
+ onClick={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ </div>
+ );
+ })}
+ <AddButton
+ name="add"
+ style={{ float: "right" }}
+ onClick={this.bindValue.bind(this)}
+ />
+ </div>
+ );
}
bindValue(e: any) {
const name = e.target.name;
- const index = e.target.getAttribute('data-index');
+ const index = e.target.getAttribute("data-index");
const items = this.props.value.items;
- if (name === 'url') {
+ if (name === "url") {
items[index] = new BlacklistItem(e.target.value, false, []);
- } else if (name === 'add') {
- items.push(new BlacklistItem('', false, []));
- } else if (name === 'delete') {
+ } else if (name === "add") {
+ items.push(new BlacklistItem("", false, []));
+ } else if (name === "delete") {
items.splice(index, 1);
}
this.props.onChange(new Blacklist(items));
- if (name === 'delete') {
+ if (name === "delete") {
this.props.onBlur();
}
}
diff --git a/src/settings/components/form/KeymapsForm.tsx b/src/settings/components/form/KeymapsForm.tsx
index dc74de3..b9af0df 100644
--- a/src/settings/components/form/KeymapsForm.tsx
+++ b/src/settings/components/form/KeymapsForm.tsx
@@ -1,8 +1,8 @@
-import './KeymapsForm.scss';
-import React from 'react';
-import Input from '../ui/Input';
-import keymaps from '../../keymaps';
-import { FormKeymaps } from '../../../shared/SettingData';
+import "./KeymapsForm.scss";
+import React from "react";
+import Input from "../ui/Input";
+import keymaps from "../../keymaps";
+import { FormKeymaps } from "../../../shared/SettingData";
interface Props {
value: FormKeymaps;
@@ -19,25 +19,31 @@ class KeymapsForm extends React.Component<Props> {
render() {
const values = this.props.value.toJSON();
- return <div className='form-keymaps-form'>
- {
- keymaps.fields.map((group, index) => {
- return <div key={index} className='form-keymaps-form-field-group'>
- {
- group.map(([name, label]) => {
- const value = values[name] || '';
- return <Input
- type='text' id={name} name={name} key={name}
- label={label} value={value}
- onValueChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />;
- })
- }
- </div>;
- })
- }
- </div>;
+ return (
+ <div className="form-keymaps-form">
+ {keymaps.fields.map((group, index) => {
+ return (
+ <div key={index} className="form-keymaps-form-field-group">
+ {group.map(([name, label]) => {
+ const value = values[name] || "";
+ return (
+ <Input
+ type="text"
+ id={name}
+ name={name}
+ key={name}
+ label={label}
+ value={value}
+ onValueChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ );
+ })}
+ </div>
+ );
+ })}
+ </div>
+ );
}
bindValue(name: string, value: string) {
diff --git a/src/settings/components/form/PartialBlacklistForm.tsx b/src/settings/components/form/PartialBlacklistForm.tsx
index 1807e28..95beee8 100644
--- a/src/settings/components/form/PartialBlacklistForm.tsx
+++ b/src/settings/components/form/PartialBlacklistForm.tsx
@@ -1,8 +1,8 @@
-import './PartialBlacklistForm.scss';
-import AddButton from '../ui/AddButton';
-import DeleteButton from '../ui/DeleteButton';
-import React from 'react';
-import Blacklist, { BlacklistItem } from '../../../shared/settings/Blacklist';
+import "./PartialBlacklistForm.scss";
+import AddButton from "../ui/AddButton";
+import DeleteButton from "../ui/DeleteButton";
+import React from "react";
+import Blacklist, { BlacklistItem } from "../../../shared/settings/Blacklist";
interface Props {
value: Blacklist;
@@ -18,59 +18,77 @@ class PartialBlacklistForm extends React.Component<Props> {
};
render() {
- return <div className='form-partial-blacklist-form'>
- <div className='form-partial-blacklist-form-header'>
- <div className='column-url'>URL</div>
- <div className='column-keys'>Keys</div>
- </div>
- {
- this.props.value.items.map((item, index) => {
+ return (
+ <div className="form-partial-blacklist-form">
+ <div className="form-partial-blacklist-form-header">
+ <div className="column-url">URL</div>
+ <div className="column-keys">Keys</div>
+ </div>
+ {this.props.value.items.map((item, index) => {
if (!item.partial) {
return null;
}
- return <div key={index} className='form-partial-blacklist-form-row'>
- <input data-index={index} type='text' name='url'
- className='column-url' value={item.pattern}
- onChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- <input data-index={index} type='text' name='keys'
- className='column-keys' value={item.keys.join(',')}
- onChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- <DeleteButton data-index={index} name='delete'
- onClick={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- </div>;
- })
- }
- <AddButton name='add' style={{ float: 'right' }}
- onClick={this.bindValue.bind(this)} />
- </div>;
+ return (
+ <div key={index} className="form-partial-blacklist-form-row">
+ <input
+ data-index={index}
+ type="text"
+ name="url"
+ className="column-url"
+ value={item.pattern}
+ onChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ <input
+ data-index={index}
+ type="text"
+ name="keys"
+ className="column-keys"
+ value={item.keys.join(",")}
+ onChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ <DeleteButton
+ data-index={index}
+ name="delete"
+ onClick={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ </div>
+ );
+ })}
+ <AddButton
+ name="add"
+ style={{ float: "right" }}
+ onClick={this.bindValue.bind(this)}
+ />
+ </div>
+ );
}
bindValue(e: any) {
const name = e.target.name;
- const index = e.target.getAttribute('data-index');
+ const index = e.target.getAttribute("data-index");
const items = this.props.value.items;
- if (name === 'url') {
+ if (name === "url") {
const current = items[index];
items[index] = new BlacklistItem(e.target.value, true, current.keys);
- } else if (name === 'keys') {
+ } else if (name === "keys") {
const current = items[index];
items[index] = new BlacklistItem(
- current.pattern, true, e.target.value.split(','));
- } else if (name === 'add') {
- items.push(new BlacklistItem('', true, []));
- } else if (name === 'delete') {
+ current.pattern,
+ true,
+ e.target.value.split(",")
+ );
+ } else if (name === "add") {
+ items.push(new BlacklistItem("", true, []));
+ } else if (name === "delete") {
items.splice(index, 1);
}
this.props.onChange(new Blacklist(items));
- if (name === 'delete') {
+ if (name === "delete") {
this.props.onBlur();
}
}
diff --git a/src/settings/components/form/PropertiesForm.tsx b/src/settings/components/form/PropertiesForm.tsx
index e648971..aebd9b1 100644
--- a/src/settings/components/form/PropertiesForm.tsx
+++ b/src/settings/components/form/PropertiesForm.tsx
@@ -1,9 +1,9 @@
-import './PropertiesForm.scss';
-import React from 'react';
+import "./PropertiesForm.scss";
+import React from "react";
interface Props {
- types: {[key: string]: string};
- value: {[key: string]: any};
+ types: { [key: string]: string };
+ value: { [key: string]: any };
onChange: (value: any) => void;
onBlur: () => void;
}
@@ -20,18 +20,18 @@ class PropertiesForm extends React.Component<Props> {
const types = this.props.types;
const values = this.props.value;
- return <div className='form-properties-form'>
- {
- Object.keys(types).map((name) => {
+ return (
+ <div className="form-properties-form">
+ {Object.keys(types).map((name) => {
const type = types[name];
- let inputType = '';
+ let inputType = "";
let onChange = this.bindValue.bind(this);
- if (type === 'string') {
- inputType = 'text';
- } else if (type === 'number') {
- inputType = 'number';
- } else if (type === 'boolean') {
- inputType = 'checkbox';
+ if (type === "string") {
+ inputType = "text";
+ } else if (type === "number") {
+ inputType = "number";
+ } else if (type === "boolean") {
+ inputType = "checkbox";
// Settings are saved onBlur, but checkbox does not fire it
onChange = (e) => {
@@ -41,29 +41,33 @@ class PropertiesForm extends React.Component<Props> {
} else {
return null;
}
- return <div key={name} className='form-properties-form-row'>
- <label>
- <span className='column-name'>{name}</span>
- <input type={inputType} name={name}
- className='column-input'
- value={values[name] ? values[name] : ''}
- onChange={onChange}
- onBlur={this.props.onBlur}
- checked={values[name]}
- />
- </label>
- </div>;
- })
- }
- </div>;
+ return (
+ <div key={name} className="form-properties-form-row">
+ <label>
+ <span className="column-name">{name}</span>
+ <input
+ type={inputType}
+ name={name}
+ className="column-input"
+ value={values[name] ? values[name] : ""}
+ onChange={onChange}
+ onBlur={this.props.onBlur}
+ checked={values[name]}
+ />
+ </label>
+ </div>
+ );
+ })}
+ </div>
+ );
}
bindValue(e: React.ChangeEvent<HTMLInputElement>) {
const name = e.target.name;
const next = { ...this.props.value };
- if (e.target.type.toLowerCase() === 'checkbox') {
+ if (e.target.type.toLowerCase() === "checkbox") {
next[name] = e.target.checked;
- } else if (e.target.type.toLowerCase() === 'number') {
+ } else if (e.target.type.toLowerCase() === "number") {
next[name] = Number(e.target.value);
} else {
next[name] = e.target.value;
diff --git a/src/settings/components/form/SearchForm.tsx b/src/settings/components/form/SearchForm.tsx
index 5dc786b..a4d923d 100644
--- a/src/settings/components/form/SearchForm.tsx
+++ b/src/settings/components/form/SearchForm.tsx
@@ -1,8 +1,8 @@
-import './SearchForm.scss';
-import React from 'react';
-import AddButton from '../ui/AddButton';
-import DeleteButton from '../ui/DeleteButton';
-import { FormSearch } from '../../../shared/SettingData';
+import "./SearchForm.scss";
+import React from "react";
+import AddButton from "../ui/AddButton";
+import DeleteButton from "../ui/DeleteButton";
+import { FormSearch } from "../../../shared/SettingData";
interface Props {
value: FormSearch;
@@ -12,68 +12,88 @@ interface Props {
class SearchForm extends React.Component<Props> {
public static defaultProps: Props = {
- value: FormSearch.fromJSON({ default: '', engines: []}),
+ value: FormSearch.fromJSON({ default: "", engines: [] }),
onChange: () => {},
onBlur: () => {},
};
render() {
const value = this.props.value.toJSON();
- return <div className='form-search-form'>
- <div className='form-search-form-header'>
- <div className='column-name'>Name</div>
- <div className='column-url'>URL</div>
- <div className='column-option'>Default</div>
- </div>
- {
- value.engines.map((engine, index) => {
- return <div key={index} className='form-search-form-row'>
- <input data-index={index} type='text' name='name'
- className='column-name' value={engine[0]}
- onChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- <input data-index={index} type='text' name='url'
- placeholder='http://example.com/?q={}'
- className='column-url' value={engine[1]}
- onChange={this.bindValue.bind(this)}
- onBlur={this.props.onBlur}
- />
- <div className='column-option'>
- <input data-index={index} type='radio' name='default'
- checked={value.default === engine[0]}
- onChange={this.bindValue.bind(this)} />
- <DeleteButton data-index={index} name='delete'
- onClick={this.bindValue.bind(this)} />
+ return (
+ <div className="form-search-form">
+ <div className="form-search-form-header">
+ <div className="column-name">Name</div>
+ <div className="column-url">URL</div>
+ <div className="column-option">Default</div>
+ </div>
+ {value.engines.map((engine, index) => {
+ return (
+ <div key={index} className="form-search-form-row">
+ <input
+ data-index={index}
+ type="text"
+ name="name"
+ className="column-name"
+ value={engine[0]}
+ onChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ <input
+ data-index={index}
+ type="text"
+ name="url"
+ placeholder="http://example.com/?q={}"
+ className="column-url"
+ value={engine[1]}
+ onChange={this.bindValue.bind(this)}
+ onBlur={this.props.onBlur}
+ />
+ <div className="column-option">
+ <input
+ data-index={index}
+ type="radio"
+ name="default"
+ checked={value.default === engine[0]}
+ onChange={this.bindValue.bind(this)}
+ />
+ <DeleteButton
+ data-index={index}
+ name="delete"
+ onClick={this.bindValue.bind(this)}
+ />
+ </div>
</div>
- </div>;
- })
- }
- <AddButton name='add' style={{ float: 'right' }}
- onClick={this.bindValue.bind(this)} />
- </div>;
+ );
+ })}
+ <AddButton
+ name="add"
+ style={{ float: "right" }}
+ onClick={this.bindValue.bind(this)}
+ />
+ </div>
+ );
}
// eslint-disable-next-line max-statements
bindValue(e: any) {
const value = this.props.value.toJSON();
const name = e.target.name;
- const index = Number(e.target.getAttribute('data-index'));
+ const index = Number(e.target.getAttribute("data-index"));
const next: typeof value = {
default: value.default,
engines: value.engines.slice(),
};
- if (name === 'name') {
+ if (name === "name") {
next.engines[index][0] = e.target.value;
next.default = value.engines[index][0];
- } else if (name === 'url') {
+ } else if (name === "url") {
next.engines[index][1] = e.target.value;
- } else if (name === 'default') {
+ } else if (name === "default") {
next.default = value.engines[index][0];
- } else if (name === 'add') {
- next.engines.push(['', '']);
- } else if (name === 'delete' && value.engines.length > 1) {
+ } else if (name === "add") {
+ next.engines.push(["", ""]);
+ } else if (name === "delete" && value.engines.length > 1) {
next.engines.splice(index, 1);
if (value.engines[index][0] === value.default) {
const nextIndex = Math.min(index, next.engines.length - 1);
@@ -82,7 +102,7 @@ class SearchForm extends React.Component<Props> {
}
this.props.onChange(FormSearch.fromJSON(next));
- if (name === 'delete' || name === 'default') {
+ if (name === "delete" || name === "default") {
this.props.onBlur();
}
}
diff --git a/src/settings/components/index.tsx b/src/settings/components/index.tsx
index f4f0326..5793a8f 100644
--- a/src/settings/components/index.tsx
+++ b/src/settings/components/index.tsx
@@ -1,32 +1,36 @@
-import './site.scss';
-import React from 'react';
-import { connect } from 'react-redux';
-import Input from './ui/Input';
-import SearchForm from './form/SearchForm';
-import KeymapsForm from './form/KeymapsForm';
-import BlacklistForm from './form/BlacklistForm';
-import PropertiesForm from './form/PropertiesForm';
-import PartialBlacklistForm from './form/PartialBlacklistForm';
-import * as settingActions from '../../settings/actions/setting';
+import "./site.scss";
+import React from "react";
+import { connect } from "react-redux";
+import Input from "./ui/Input";
+import SearchForm from "./form/SearchForm";
+import KeymapsForm from "./form/KeymapsForm";
+import BlacklistForm from "./form/BlacklistForm";
+import PropertiesForm from "./form/PropertiesForm";
+import PartialBlacklistForm from "./form/PartialBlacklistForm";
+import * as settingActions from "../../settings/actions/setting";
import SettingData, {
- FormKeymaps, FormSearch, FormSettings, JSONTextSettings,
-} from '../../shared/SettingData';
-import { State as AppState } from '../reducers/setting';
-import Properties from '../../shared/settings/Properties';
-import Blacklist from '../../shared/settings/Blacklist';
+ FormKeymaps,
+ FormSearch,
+ FormSettings,
+ JSONTextSettings,
+} from "../../shared/SettingData";
+import { State as AppState } from "../reducers/setting";
+import Properties from "../../shared/settings/Properties";
+import Blacklist from "../../shared/settings/Blacklist";
const DO_YOU_WANT_TO_CONTINUE =
- 'Some settings in JSON can be lost when migrating. ' +
- 'Do you want to continue?';
+ "Some settings in JSON can be lost when migrating. " +
+ "Do you want to continue?";
type StateProps = ReturnType<typeof mapStateToProps>;
interface DispatchProps {
- dispatch: (action: any) => void,
+ dispatch: (action: any) => void;
}
-type Props = StateProps & DispatchProps & {
- // FIXME
- store: any;
-};
+type Props = StateProps &
+ DispatchProps & {
+ // FIXME
+ store: any;
+ };
class SettingsComponent extends React.Component<Props> {
componentDidMount() {
@@ -34,97 +38,103 @@ class SettingsComponent extends React.Component<Props> {
}
renderFormFields(form: FormSettings) {
- return <div>
- <fieldset>
- <legend>Keybindings</legend>
- <KeymapsForm
- value={form.keymaps}
- onChange={this.bindKeymapsForm.bind(this)}
- onBlur={this.save.bind(this)}
- />
- </fieldset>
- <fieldset>
- <legend>Search Engines</legend>
- <SearchForm
- value={form.search}
- onChange={this.bindSearchForm.bind(this)}
- onBlur={this.save.bind(this)}
- />
- </fieldset>
- <fieldset>
- <legend>Blacklist</legend>
- <BlacklistForm
- value={form.blacklist}
- onChange={this.bindBlacklistForm.bind(this)}
- onBlur={this.save.bind(this)}
- />
- </fieldset>
- <fieldset>
- <legend>Partial blacklist</legend>
- <PartialBlacklistForm
- value={form.blacklist}
- onChange={this.bindBlacklistForm.bind(this)}
- onBlur={this.save.bind(this)}
- />
- </fieldset>
- <fieldset>
- <legend>Properties</legend>
- <PropertiesForm
- types={Properties.types()}
- value={form.properties.toJSON()}
- onChange={this.bindPropertiesForm.bind(this)}
- onBlur={this.save.bind(this)}
- />
- </fieldset>
- </div>;
+ return (
+ <div>
+ <fieldset>
+ <legend>Keybindings</legend>
+ <KeymapsForm
+ value={form.keymaps}
+ onChange={this.bindKeymapsForm.bind(this)}
+ onBlur={this.save.bind(this)}
+ />
+ </fieldset>
+ <fieldset>
+ <legend>Search Engines</legend>
+ <SearchForm
+ value={form.search}
+ onChange={this.bindSearchForm.bind(this)}
+ onBlur={this.save.bind(this)}
+ />
+ </fieldset>
+ <fieldset>
+ <legend>Blacklist</legend>
+ <BlacklistForm
+ value={form.blacklist}
+ onChange={this.bindBlacklistForm.bind(this)}
+ onBlur={this.save.bind(this)}
+ />
+ </fieldset>
+ <fieldset>
+ <legend>Partial blacklist</legend>
+ <PartialBlacklistForm
+ value={form.blacklist}
+ onChange={this.bindBlacklistForm.bind(this)}
+ onBlur={this.save.bind(this)}
+ />
+ </fieldset>
+ <fieldset>
+ <legend>Properties</legend>
+ <PropertiesForm
+ types={Properties.types()}
+ value={form.properties.toJSON()}
+ onChange={this.bindPropertiesForm.bind(this)}
+ onBlur={this.save.bind(this)}
+ />
+ </fieldset>
+ </div>
+ );
}
renderJsonFields(json: JSONTextSettings, error: string) {
- return <div>
- <Input
- type='textarea'
- name='json'
- label='Plain JSON'
- spellCheck={false}
- error={error}
- onValueChange={this.bindJson.bind(this)}
- onBlur={this.save.bind(this)}
- value={json.toJSONText()}
- />
- </div>;
+ return (
+ <div>
+ <Input
+ type="textarea"
+ name="json"
+ label="Plain JSON"
+ spellCheck={false}
+ error={error}
+ onValueChange={this.bindJson.bind(this)}
+ onBlur={this.save.bind(this)}
+ value={json.toJSONText()}
+ />
+ </div>
+ );
}
render() {
let fields = null;
const disabled = this.props.error.length > 0;
- if (this.props.source === 'form') {
+ if (this.props.source === "form") {
fields = this.renderFormFields(this.props.form!!);
- } else if (this.props.source === 'json') {
+ } else if (this.props.source === "json") {
fields = this.renderJsonFields(this.props.json!!, this.props.error);
}
return (
<div>
<h1>Configure Vim-Vixen</h1>
- <form className='vimvixen-settings-form'>
+ <form className="vimvixen-settings-form">
<Input
- type='radio'
- id='setting-source-form'
- name='source'
- label='Use form'
- checked={this.props.source === 'form'}
- value='form'
+ type="radio"
+ id="setting-source-form"
+ name="source"
+ label="Use form"
+ checked={this.props.source === "form"}
+ value="form"
onValueChange={this.bindSource.bind(this)}
- disabled={disabled} />
+ disabled={disabled}
+ />
<Input
- type='radio'
- name='source'
- label='Use plain JSON'
- checked={this.props.source === 'json'}
- value='json'
+ type="radio"
+ name="source"
+ label="Use plain JSON"
+ checked={this.props.source === "json"}
+ value="json"
onValueChange={this.bindSource.bind(this)}
- disabled={disabled} />
- { fields }
+ disabled={disabled}
+ />
+ {fields}
</form>
</div>
);
@@ -142,7 +152,8 @@ class SettingsComponent extends React.Component<Props> {
const data = new SettingData({
source: this.props.source,
form: (this.props.form as FormSettings).buildWithSearch(
- FormSearch.fromJSON(value)),
+ FormSearch.fromJSON(value)
+ ),
});
this.props.dispatch(settingActions.set(data));
}
@@ -159,7 +170,8 @@ class SettingsComponent extends React.Component<Props> {
const data = new SettingData({
source: this.props.source,
form: (this.props.form as FormSettings).buildWithProperties(
- Properties.fromJSON(value))
+ Properties.fromJSON(value)
+ ),
});
this.props.dispatch(settingActions.set(data));
}
@@ -174,27 +186,29 @@ class SettingsComponent extends React.Component<Props> {
bindSource(_name: string, value: string) {
const from = this.props.source;
- if (from === 'form' && value === 'json') {
- this.props.dispatch(settingActions.switchToJson(
- this.props.form as FormSettings));
+ if (from === "form" && value === "json") {
+ this.props.dispatch(
+ settingActions.switchToJson(this.props.form as FormSettings)
+ );
this.save();
- } else if (from === 'json' && value === 'form') {
+ } else if (from === "json" && value === "form") {
const b = window.confirm(DO_YOU_WANT_TO_CONTINUE);
if (!b) {
this.forceUpdate();
return;
}
this.props.dispatch(
- settingActions.switchToForm(this.props.json as JSONTextSettings));
+ settingActions.switchToForm(this.props.json as JSONTextSettings)
+ );
this.save();
}
}
save() {
const { source, json, form } = this.props.store.getState();
- this.props.dispatch(settingActions.save(
- new SettingData({ source, json, form }),
- ));
+ this.props.dispatch(
+ settingActions.save(new SettingData({ source, json, form }))
+ );
}
}
diff --git a/src/settings/components/ui/AddButton.tsx b/src/settings/components/ui/AddButton.tsx
index bb76d08..c15a732 100644
--- a/src/settings/components/ui/AddButton.tsx
+++ b/src/settings/components/ui/AddButton.tsx
@@ -1,13 +1,18 @@
-import './AddButton.scss';
-import React from 'react';
+import "./AddButton.scss";
+import React from "react";
type Props = React.AllHTMLAttributes<HTMLInputElement>;
class AddButton extends React.Component<Props> {
render() {
- return <input
- className='ui-add-button' type='button' value='&#x271a;'
- {...this.props} />;
+ return (
+ <input
+ className="ui-add-button"
+ type="button"
+ value="&#x271a;"
+ {...this.props}
+ />
+ );
}
}
diff --git a/src/settings/components/ui/DeleteButton.tsx b/src/settings/components/ui/DeleteButton.tsx
index e666426..df8976e 100644
--- a/src/settings/components/ui/DeleteButton.tsx
+++ b/src/settings/components/ui/DeleteButton.tsx
@@ -1,13 +1,18 @@
-import './DeleteButton.scss';
-import React from 'react';
+import "./DeleteButton.scss";
+import React from "react";
type Props = React.AllHTMLAttributes<HTMLInputElement>;
class DeleteButton extends React.Component<Props> {
render() {
- return <input
- className='ui-delete-button' type='button' value='&#x2716;'
- {...this.props} />;
+ return (
+ <input
+ className="ui-delete-button"
+ type="button"
+ value="&#x2716;"
+ {...this.props}
+ />
+ );
}
}
diff --git a/src/settings/components/ui/Input.tsx b/src/settings/components/ui/Input.tsx
index 69c14b3..6819ddb 100644
--- a/src/settings/components/ui/Input.tsx
+++ b/src/settings/components/ui/Input.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
-import './Input.scss';
+import React from "react";
+import "./Input.scss";
interface Props extends React.AllHTMLAttributes<HTMLElement> {
name: string;
@@ -13,66 +13,75 @@ interface Props extends React.AllHTMLAttributes<HTMLElement> {
class Input extends React.Component<Props> {
renderText(props: Props) {
- const inputClassName = props.error ? 'input-error' : '';
+ const inputClassName = props.error ? "input-error" : "";
const pp = { ...props };
delete pp.onValueChange;
- return <div className='settings-ui-input'>
- <label htmlFor={props.id}>{ props.label }</label>
- <input
- type='text' className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
- { ...pp } />
- </div>;
+ return (
+ <div className="settings-ui-input">
+ <label htmlFor={props.id}>{props.label}</label>
+ <input
+ type="text"
+ className={inputClassName}
+ onChange={this.bindOnChange.bind(this)}
+ {...pp}
+ />
+ </div>
+ );
}
renderRadio(props: Props) {
- const inputClassName = props.error ? 'input-error' : '';
+ const inputClassName = props.error ? "input-error" : "";
const pp = { ...props };
delete pp.onValueChange;
- return <div className='settings-ui-input'>
- <label>
- <input
- type='radio' className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
- { ...pp } />
- { props.label }
- </label>
- </div>;
+ return (
+ <div className="settings-ui-input">
+ <label>
+ <input
+ type="radio"
+ className={inputClassName}
+ onChange={this.bindOnChange.bind(this)}
+ {...pp}
+ />
+ {props.label}
+ </label>
+ </div>
+ );
}
renderTextArea(props: Props) {
- const inputClassName = props.error ? 'input-error' : '';
+ const inputClassName = props.error ? "input-error" : "";
const pp = { ...props };
delete pp.onValueChange;
- return <div className='settings-ui-input'>
- <label
- htmlFor={props.id}
- >{ props.label }</label>
- <textarea
- className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
- { ...pp } />
- <p className='settings-ui-input-error'>{ this.props.error }</p>
- </div>;
+ return (
+ <div className="settings-ui-input">
+ <label htmlFor={props.id}>{props.label}</label>
+ <textarea
+ className={inputClassName}
+ onChange={this.bindOnChange.bind(this)}
+ {...pp}
+ />
+ <p className="settings-ui-input-error">{this.props.error}</p>
+ </div>
+ );
}
render() {
const { type } = this.props;
switch (this.props.type) {
- case 'text':
- return this.renderText(this.props);
- case 'radio':
- return this.renderRadio(this.props);
- case 'textarea':
- return this.renderTextArea(this.props);
- default:
- console.warn(`Unsupported input type ${type}`);
+ case "text":
+ return this.renderText(this.props);
+ case "radio":
+ return this.renderRadio(this.props);
+ case "textarea":
+ return this.renderTextArea(this.props);
+ default:
+ console.warn(`Unsupported input type ${type}`);
}
return null;
}
- bindOnChange(e: React.ChangeEvent<HTMLInputElement|HTMLTextAreaElement>) {
+ bindOnChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
if (this.props.onValueChange) {
this.props.onValueChange(e.target.name, e.target.value);
}
diff --git a/src/settings/index.tsx b/src/settings/index.tsx
index cde4488..0d3364b 100644
--- a/src/settings/index.tsx
+++ b/src/settings/index.tsx
@@ -1,18 +1,15 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import SettingsComponent from './components';
-import reducer from './reducers/setting';
-import { Provider } from 'react-redux';
-import promise from 'redux-promise';
-import { createStore, applyMiddleware } from 'redux';
+import React from "react";
+import ReactDOM from "react-dom";
+import SettingsComponent from "./components";
+import reducer from "./reducers/setting";
+import { Provider } from "react-redux";
+import promise from "redux-promise";
+import { createStore, applyMiddleware } from "redux";
-const store = createStore(
- reducer,
- applyMiddleware(promise),
-);
+const store = createStore(reducer, applyMiddleware(promise));
-document.addEventListener('DOMContentLoaded', () => {
- const wrapper = document.getElementById('vimvixen-settings');
+document.addEventListener("DOMContentLoaded", () => {
+ const wrapper = document.getElementById("vimvixen-settings");
ReactDOM.render(
<Provider store={store}>
<SettingsComponent store={store} />
diff --git a/src/settings/keymaps.ts b/src/settings/keymaps.ts
index 24ba1a5..25c7a51 100644
--- a/src/settings/keymaps.ts
+++ b/src/settings/keymaps.ts
@@ -2,70 +2,79 @@
const fields = [
[
- ['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 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 down by half of screen'],
- ['scroll.pages?{"count":-1}', 'Scroll up by a screen'],
- ['scroll.pages?{"count":1}', 'Scroll down by a screen'],
- ], [
- ['mark.set.prefix', 'Set mark at current position'],
- ['mark.jump.prefix', 'Jump to the mark'],
- ], [
- ['tabs.close?{"select":"right"}', 'Close a tab'],
- ['tabs.close.right', 'Close all tabs to the right'],
- ['tabs.reopen', 'Reopen closed tab'],
- ['tabs.next', 'Select next tab'],
- ['tabs.prev', 'Select prev tab'],
- ['tabs.first', 'Select first tab'],
- ['tabs.last', 'Select last tab'],
- ['tabs.reload?{"cache":false}', 'Reload current tab'],
- ['tabs.reload?{"cache":true}', 'Reload with no caches'],
- ['tabs.pin.toggle', 'Toggle pinned state'],
- ['tabs.duplicate', 'Duplicate a tab'],
- ], [
- ['follow.start?{"newTab":false,"background":false}', 'Follow a link'],
- ['follow.start?{"newTab":true,"background":false}', 'Follow a link in new tab'],
- ['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'],
- ['navigate.root', 'Go to root directory'],
- ['page.source', 'Open page source'],
- ['page.home?{"newTab":false}', 'Open start page to current tab'],
- ['page.home?{"newTab":true}', 'Open start page in new tab'],
- ['focus.input', 'Focus input'],
- ], [
- ['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'],
- ['command.show.addbookmark?{"alter":true}', 'Open addbookmark command'],
- ], [
- ['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'],
- ['repeat.last', 'Repeat last change'],
- ]
+ ['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 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 down by half of screen"],
+ ['scroll.pages?{"count":-1}', "Scroll up by a screen"],
+ ['scroll.pages?{"count":1}', "Scroll down by a screen"],
+ ],
+ [
+ ["mark.set.prefix", "Set mark at current position"],
+ ["mark.jump.prefix", "Jump to the mark"],
+ ],
+ [
+ ['tabs.close?{"select":"right"}', "Close a tab"],
+ ["tabs.close.right", "Close all tabs to the right"],
+ ["tabs.reopen", "Reopen closed tab"],
+ ["tabs.next", "Select next tab"],
+ ["tabs.prev", "Select prev tab"],
+ ["tabs.first", "Select first tab"],
+ ["tabs.last", "Select last tab"],
+ ['tabs.reload?{"cache":false}', "Reload current tab"],
+ ['tabs.reload?{"cache":true}', "Reload with no caches"],
+ ["tabs.pin.toggle", "Toggle pinned state"],
+ ["tabs.duplicate", "Duplicate a tab"],
+ ],
+ [
+ ['follow.start?{"newTab":false,"background":false}', "Follow a link"],
+ [
+ 'follow.start?{"newTab":true,"background":false}',
+ "Follow a link in new tab",
+ ],
+ ["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"],
+ ["navigate.root", "Go to root directory"],
+ ["page.source", "Open page source"],
+ ['page.home?{"newTab":false}', "Open start page to current tab"],
+ ['page.home?{"newTab":true}', "Open start page in new tab"],
+ ["focus.input", "Focus input"],
+ ],
+ [
+ ["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"],
+ ['command.show.addbookmark?{"alter":true}', "Open addbookmark command"],
+ ],
+ [
+ ["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"],
+ ["repeat.last", "Repeat last change"],
+ ],
];
export default {
diff --git a/src/settings/reducers/setting.ts b/src/settings/reducers/setting.ts
index 804853f..31544bb 100644
--- a/src/settings/reducers/setting.ts
+++ b/src/settings/reducers/setting.ts
@@ -1,8 +1,10 @@
-import * as actions from '../actions';
+import * as actions from "../actions";
import {
- JSONTextSettings, FormSettings, SettingSource,
-} from '../../shared/SettingData';
-import { DefaultSetting } from '../../shared/settings/Settings';
+ JSONTextSettings,
+ FormSettings,
+ SettingSource,
+} from "../../shared/SettingData";
+import { DefaultSetting } from "../../shared/settings/Settings";
export interface State {
source: SettingSource;
@@ -13,37 +15,41 @@ export interface State {
const defaultState: State = {
source: SettingSource.JSON,
- json: JSONTextSettings.fromText(''),
+ json: JSONTextSettings.fromText(""),
form: FormSettings.fromSettings(DefaultSetting),
- error: '',
+ error: "",
};
export default function reducer(
state = defaultState,
- action: actions.SettingAction,
+ action: actions.SettingAction
): State {
switch (action.type) {
- case actions.SETTING_SET_SETTINGS:
- return { ...state,
- source: action.source,
- json: action.json,
- form: action.form,
- error: '', };
- case actions.SETTING_SHOW_ERROR:
- return { ...state,
- error: action.error,
- json: action.json, };
- case actions.SETTING_SWITCH_TO_FORM:
- return { ...state,
- error: '',
- source: SettingSource.Form,
- form: action.form, };
- case actions.SETTING_SWITCH_TO_JSON:
- return { ...state,
- error: '',
- source: SettingSource.JSON,
- json: action.json, };
- default:
- return state;
+ case actions.SETTING_SET_SETTINGS:
+ return {
+ ...state,
+ source: action.source,
+ json: action.json,
+ form: action.form,
+ error: "",
+ };
+ case actions.SETTING_SHOW_ERROR:
+ return { ...state, error: action.error, json: action.json };
+ case actions.SETTING_SWITCH_TO_FORM:
+ return {
+ ...state,
+ error: "",
+ source: SettingSource.Form,
+ form: action.form,
+ };
+ case actions.SETTING_SWITCH_TO_JSON:
+ return {
+ ...state,
+ error: "",
+ source: SettingSource.JSON,
+ json: action.json,
+ };
+ default:
+ return state;
}
}
diff --git a/src/settings/storage.ts b/src/settings/storage.ts
index 55cca96..da67ecc 100644
--- a/src/settings/storage.ts
+++ b/src/settings/storage.ts
@@ -1,22 +1,24 @@
-import SettingData, { DefaultSettingData } from '../shared/SettingData';
+import SettingData, { DefaultSettingData } from "../shared/SettingData";
-const loadSettingData = async(): Promise<SettingData> => {
- const { settings: syncSettings } = await browser.storage.sync.get('settings');
+const loadSettingData = async (): Promise<SettingData> => {
+ const { settings: syncSettings } = await browser.storage.sync.get("settings");
if (syncSettings) {
return SettingData.fromJSON(syncSettings as any);
}
- const { settings: localSettings } = await browser.storage.local.get('settings');
+ const { settings: localSettings } = await browser.storage.local.get(
+ "settings"
+ );
if (localSettings) {
return SettingData.fromJSON(localSettings as any);
}
- return DefaultSettingData
+ return DefaultSettingData;
};
-export const load = async(): Promise<SettingData> => {
+export const load = async (): Promise<SettingData> => {
try {
return loadSettingData();
} catch (e) {
- console.error('unable to load settings', e);
+ console.error("unable to load settings", e);
return DefaultSettingData;
}
};