import React from "react"; import { connect } from "react-redux"; import styled from "styled-components"; import TextArea from "./ui/TextArea"; import Radio from "./ui/Radio"; 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"; const Container = styled.form` padding: 2px; font-family: system-ui; `; const Fieldset = styled.fieldset` margin: 0; padding: 0; border: none; margin-top: 1rem; &:first-of-type { margin-top: 1rem; } `; const Legend = styled.legend` font-size: 1.5rem; padding: 0.5rem 0; font-weight: bold; `; const 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; } type Props = StateProps & DispatchProps & { // FIXME store: any; }; class SettingsComponent extends React.Component<Props> { componentDidMount() { this.props.dispatch(settingActions.load()); } 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> ); } renderJsonFields(json: JSONTextSettings, error: string) { return ( <div> <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") { fields = this.renderFormFields(this.props.form!); } else if (this.props.source === "json") { fields = this.renderJsonFields(this.props.json!, this.props.error); } return ( <Container> <h1>Configure Vim-Vixen</h1> <Radio id="setting-source-form" name="source" label="Use form" checked={this.props.source === "form"} value="form" onValueChange={this.bindSource.bind(this)} disabled={disabled} /> <Radio name="source" label="Use plain JSON" checked={this.props.source === "json"} value="json" onValueChange={this.bindSource.bind(this)} disabled={disabled} /> {fields} </Container> ); } bindKeymapsForm(value: FormKeymaps) { const data = new SettingData({ source: this.props.source, form: (this.props.form as FormSettings).buildWithKeymaps(value), }); this.props.dispatch(settingActions.set(data)); } bindSearchForm(value: any) { const data = new SettingData({ source: this.props.source, form: (this.props.form as FormSettings).buildWithSearch( FormSearch.fromJSON(value) ), }); this.props.dispatch(settingActions.set(data)); } bindBlacklistForm(blacklist: Blacklist) { const data = new SettingData({ source: this.props.source, form: (this.props.form as FormSettings).buildWithBlacklist(blacklist), }); this.props.dispatch(settingActions.set(data)); } bindPropertiesForm(value: any) { const data = new SettingData({ source: this.props.source, form: (this.props.form as FormSettings).buildWithProperties( Properties.fromJSON(value) ), }); this.props.dispatch(settingActions.set(data)); } bindJson(_name: string, value: string) { const data = new SettingData({ source: this.props.source, json: JSONTextSettings.fromText(value), }); this.props.dispatch(settingActions.set(data)); } 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) ); this.save(); } 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) ); this.save(); } } save() { const { source, json, form } = this.props.store.getState(); this.props.dispatch( settingActions.save(new SettingData({ source, json, form })) ); } } const mapStateToProps = (state: AppState) => ({ ...state }); export default connect(mapStateToProps)(SettingsComponent);