Clean up some things

This commit is contained in:
Ken-Håvard Lieng 2018-05-25 04:12:02 +02:00
parent e2a895a1b9
commit e7cff1686e
9 changed files with 121 additions and 135 deletions

View file

@ -62,9 +62,7 @@ export default class TabList extends PureComponent {
return (
<div className={className}>
<button className="button-connect" onClick={this.handleConnectClick}>
Connect
</button>
<button onClick={this.handleConnectClick}>Connect</button>
<div className="tab-container">{tabs}</div>
<div className="side-buttons">
<i className="icon-user" />

View file

@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';
import Editable from 'components/ui/Editable';
import { isValidNick } from 'utils';
export default class MessageInput extends PureComponent {
state = {
@ -53,7 +54,11 @@ export default class MessageInput extends PureComponent {
return (
<div className="message-input-wrap">
<Editable
className="message-input-nick"
className={
isValidNick(nick)
? 'message-input-nick'
: 'message-input-nick invalid'
}
value={nick}
onBlur={onNickEditDone}
onChange={onNickChange}

View file

@ -11,9 +11,6 @@ const getSortedDefaultChannels = createSelector(
channels => channels.split(',').sort()
);
const Error = ({ children }) =>
children ? <div className="form-error">{children}</div> : null;
class Connect extends Component {
state = {
showOptionals: false
@ -21,32 +18,35 @@ class Connect extends Component {
handleSSLChange = e => {
const { values, setFieldValue } = this.props;
if (e.target.checked && values.port === '6667') {
setFieldValue('port', '6697', false);
} else if (!e.target.checked && values.port === '6697') {
setFieldValue('port', '6667', false);
if (e.target.checked && values.port === 6667) {
setFieldValue('port', 6697, false);
} else if (!e.target.checked && values.port === 6697) {
setFieldValue('port', 6667, false);
}
setFieldValue('tls', e.target.checked);
};
handleShowClick = () => {
this.setState({ showOptionals: !this.state.showOptionals });
};
renderOptionals = () => {
const { errors, touched } = this.props;
return (
<div>
<TextInput name="username" placeholder="Username" />
{touched.username && <Error>{errors.username}</Error>}
<TextInput type="password" name="password" placeholder="Password" />
<TextInput name="realname" placeholder="Realname" />
</div>
);
renderOptionals = () => (
<div>
<TextInput name="username" placeholder="Username" />
{this.renderError('username')}
<TextInput type="password" name="password" placeholder="Password" />
<TextInput name="realname" placeholder="Realname" />
</div>
);
renderError = name => {
const { touched, errors } = this.props;
if (touched[name] && errors[name]) {
return <div className="form-error">{errors[name]}</div>;
}
};
render() {
const { defaults, values, errors, touched } = this.props;
const { defaults, values } = this.props;
const { readonly, showDetails } = defaults;
let form;
@ -65,8 +65,8 @@ class Connect extends Component {
</div>
)}
<TextInput name="nick" placeholder="Nick" />
{touched.nick && <Error>{errors.nick}</Error>}
<input type="submit" value="Connect" />
{this.renderError('nick')}
<button>Connect</button>
</Form>
);
} else {
@ -76,18 +76,18 @@ class Connect extends Component {
<TextInput name="name" placeholder="Name" />
<div className="connect-form-address">
<TextInput name="host" placeholder="Host" />
<TextInput name="port" placeholder="Port" />
<TextInput name="port" type="number" placeholder="Port" />
<Checkbox name="tls" label="SSL" onChange={this.handleSSLChange} />
</div>
{touched.host && <Error>{errors.host}</Error>}
{touched.port && <Error>{errors.port}</Error>}
{this.renderError('host')}
{this.renderError('port')}
<TextInput name="nick" placeholder="Nick" />
{touched.nick && <Error>{errors.nick}</Error>}
{this.renderError('nick')}
<TextInput name="channels" placeholder="Channels" />
{touched.channels && <Error>{errors.channels}</Error>}
{this.renderError('channels')}
{this.state.showOptionals && this.renderOptionals()}
<i className="icon-ellipsis" onClick={this.handleShowClick} />
<input type="submit" value="Connect" />
<button>Connect</button>
</Form>
);
}
@ -103,11 +103,11 @@ class Connect extends Component {
export default withFormik({
mapPropsToValues: ({ defaults }) => {
let port = '6667';
let port = 6667;
if (defaults.port) {
port = `${defaults.port}`;
({ port } = defaults);
} else if (defaults.ssl) {
port = '6697';
port = 6697;
}
return {
@ -138,7 +138,7 @@ export default withFormik({
}
if (!values.port) {
values.port = values.tls ? '6697' : '6667';
values.port = values.tls ? 6697 : 6667;
} else if (!isInt(values.port, 1, 65535)) {
errors.port = 'Invalid port';
}
@ -178,6 +178,7 @@ export default withFormik({
const channels = values.channels.split(',');
delete values.channels;
values.port = `${values.port}`;
connect(values);
select(values.host);

View file

@ -12,32 +12,31 @@ export default class Editable extends PureComponent {
componentWillReceiveProps(nextProps) {
if (this.state.editing && nextProps.value !== this.props.value) {
this.setState({
width: this.getInputWidth(nextProps.value)
});
this.updateInputWidth(nextProps.value);
}
}
componentDidUpdate(prevProps, prevState) {
if (!prevState.editing && this.state.editing) {
// eslint-disable-next-line react/no-did-update-set-state
this.setState({
width: this.getInputWidth(this.props.value)
});
this.updateInputWidth(this.props.value);
}
}
getInputWidth(value) {
updateInputWidth = value => {
if (this.input) {
const style = window.getComputedStyle(this.input);
const padding =
parseInt(style.paddingLeft, 10) + parseInt(style.paddingRight, 10);
const padding = parseInt(style.paddingRight, 10);
// Make sure the width is atleast 1px so the caret always shows
const width =
stringWidth(value, `${style.fontSize} ${style.fontFamily}`) || 1;
return padding + width;
this.setState({
width: width + padding * 2,
indent: padding
});
}
}
};
startEditing = () => {
if (this.props.editable) {
@ -84,7 +83,9 @@ export default class Editable extends PureComponent {
const { children, className, value } = this.props;
const style = {
width: this.state.width
width: this.state.width,
textIndent: this.state.indent,
paddingLeft: 0
};
return this.state.editing ? (

View file

@ -10,6 +10,9 @@ const TextInput = ({ name, placeholder, ...props }) => (
className={field.value ? 'value' : null}
type="text"
name={name}
autoCorrect="off"
autoComplete="off"
spellCheck="false"
{...field}
{...props}
/>

View file

@ -1,5 +1,5 @@
import React from 'react';
import { isChannel, isValidNick, isValidChannel, isValidUsername, isInt } from '..';
import { isChannel, isValidNick, isValidChannel, isValidUsername } from '..';
import linkify from '../linkify';
describe('isChannel()', () => {
@ -76,22 +76,6 @@ describe('isValidUsername()', () => {
));
});
describe('isInt()', () => {
it('validates integers', () => {
expect(isInt('0')).toBe(true);
expect(isInt('1337')).toBe(true);
expect(isInt('0', 0, 65535)).toBe(true);
expect(isInt('0', 1, 65535)).toBe(false);
expect(isInt('1', 1, 65535)).toBe(true);
expect(isInt('65535', 1, 65535)).toBe(true);
expect(isInt('00065535', 1, 65535)).toBe(true);
expect(isInt('65536', 1, 65535)).toBe(false);
expect(isInt('1cake', 1, 65535)).toBe(false);
expect(isInt('cake1', 1, 65535)).toBe(false);
expect(isInt('', 1, 65535)).toBe(false);
});
});
describe('linkify()', () => {
const proto = href => (href.indexOf('http') !== 0 ? `http://${href}` : href);
const linkTo = href => (

View file

@ -122,18 +122,11 @@ export function isValidUsername(username) {
return true;
}
export function isInt(str, min, max) {
if (!str || str < min || str > max) {
export function isInt(i, min, max) {
if (i < min || i > max || Math.floor(i) !== i) {
return false;
}
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
if (char < 48 || char > 57) {
return false;
}
}
return true;
}