Clean up some things
This commit is contained in:
parent
e2a895a1b9
commit
e7cff1686e
File diff suppressed because one or more lines are too long
@ -29,13 +29,30 @@ input {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input::-ms-clear {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background: #6bb758;
|
||||||
|
color: #fff;
|
||||||
font: 16px Montserrat, sans-serif;
|
font: 16px Montserrat, sans-serif;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
user-select: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #7bbf6a;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
background: #6bb758;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
@ -45,6 +62,11 @@ i[class*=' icon-']:before {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
background: #ddd;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
.success {
|
.success {
|
||||||
color: #6bb758 !important;
|
color: #6bb758 !important;
|
||||||
}
|
}
|
||||||
@ -59,13 +81,7 @@ i[class*=' icon-']:before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.textinput input {
|
.textinput input {
|
||||||
padding: 17.5px 15px;
|
padding: 25px 15px 10px;
|
||||||
}
|
|
||||||
|
|
||||||
.textinput input:focus,
|
|
||||||
.textinput input.value {
|
|
||||||
padding-top: 25px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.textinput span {
|
.textinput span {
|
||||||
@ -73,6 +89,7 @@ i[class*=' icon-']:before {
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
transform: translateZ(0);
|
transform: translateZ(0);
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
color: #777;
|
color: #777;
|
||||||
@ -144,6 +161,7 @@ i[class*=' icon-']:before {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: Montserrat, sans-serif;
|
font-family: Montserrat, sans-serif;
|
||||||
transition: transform 0.2s;
|
transition: transform 0.2s;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-container {
|
.tab-container {
|
||||||
@ -200,21 +218,6 @@ i[class*=' icon-']:before {
|
|||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-connect {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
background: #6bb758;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-connect:hover {
|
|
||||||
background: #7bbf6a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-connect:active {
|
|
||||||
background: #6bb758;
|
|
||||||
}
|
|
||||||
|
|
||||||
.side-buttons {
|
.side-buttons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -293,31 +296,26 @@ i[class*=' icon-']:before {
|
|||||||
|
|
||||||
.connect-form input {
|
.connect-form input {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connect-form input[type='submit'],
|
|
||||||
.connect-form input[type='text'],
|
|
||||||
.connect-form input[type='password'] {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connect-form input[type='submit'] {
|
input[type='number'] {
|
||||||
height: 50px;
|
appearance: textfield;
|
||||||
margin-top: 0;
|
}
|
||||||
|
|
||||||
|
input::-webkit-outer-spin-button,
|
||||||
|
input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none !important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connect-form label {
|
||||||
|
user-select: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connect-form button {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
font-family: Montserrat, sans-serif;
|
|
||||||
background: #6bb758;
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connect-form input[type='submit']:hover {
|
|
||||||
background: #7bbf6a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.connect-form input[type='submit']:active {
|
|
||||||
background: #6bb758;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.connect-form-address {
|
.connect-form-address {
|
||||||
@ -426,15 +424,20 @@ i[class*=' icon-']:before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chat-title {
|
.chat-title {
|
||||||
margin-left: 15px;
|
margin-left: 10px;
|
||||||
|
padding: 0 5px;
|
||||||
font: 24px Montserrat, sans-serif;
|
font: 24px Montserrat, sans-serif;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background: none;
|
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-server .chat-title {
|
.chat-server .chat-title {
|
||||||
padding-right: 1px;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.chat-title {
|
||||||
|
background: none;
|
||||||
|
cursor: text !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-topic-wrap {
|
.chat-topic-wrap {
|
||||||
@ -617,10 +620,19 @@ i[class*=' icon-']:before {
|
|||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
background: #6bb758 !important;
|
background: #6bb758;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: Montserrat, sans-serif !important;
|
font-family: Montserrat, sans-serif !important;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.message-input-nick {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.message-input-nick.invalid {
|
||||||
|
background: #f6546a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-input {
|
.message-input {
|
||||||
@ -670,20 +682,9 @@ i[class*=' icon-']:before {
|
|||||||
|
|
||||||
.settings button {
|
.settings button {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
color: #fff;
|
|
||||||
background: #6bb758;
|
|
||||||
padding: 10px 20px;
|
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings button:hover {
|
|
||||||
background: #7bbf6a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings button:active {
|
|
||||||
background: #6bb758;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings div {
|
.settings div {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,7 @@ export default class TabList extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<button className="button-connect" onClick={this.handleConnectClick}>
|
<button onClick={this.handleConnectClick}>Connect</button>
|
||||||
Connect
|
|
||||||
</button>
|
|
||||||
<div className="tab-container">{tabs}</div>
|
<div className="tab-container">{tabs}</div>
|
||||||
<div className="side-buttons">
|
<div className="side-buttons">
|
||||||
<i className="icon-user" />
|
<i className="icon-user" />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import Editable from 'components/ui/Editable';
|
import Editable from 'components/ui/Editable';
|
||||||
|
import { isValidNick } from 'utils';
|
||||||
|
|
||||||
export default class MessageInput extends PureComponent {
|
export default class MessageInput extends PureComponent {
|
||||||
state = {
|
state = {
|
||||||
@ -53,7 +54,11 @@ export default class MessageInput extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div className="message-input-wrap">
|
<div className="message-input-wrap">
|
||||||
<Editable
|
<Editable
|
||||||
className="message-input-nick"
|
className={
|
||||||
|
isValidNick(nick)
|
||||||
|
? 'message-input-nick'
|
||||||
|
: 'message-input-nick invalid'
|
||||||
|
}
|
||||||
value={nick}
|
value={nick}
|
||||||
onBlur={onNickEditDone}
|
onBlur={onNickEditDone}
|
||||||
onChange={onNickChange}
|
onChange={onNickChange}
|
||||||
|
@ -11,9 +11,6 @@ const getSortedDefaultChannels = createSelector(
|
|||||||
channels => channels.split(',').sort()
|
channels => channels.split(',').sort()
|
||||||
);
|
);
|
||||||
|
|
||||||
const Error = ({ children }) =>
|
|
||||||
children ? <div className="form-error">{children}</div> : null;
|
|
||||||
|
|
||||||
class Connect extends Component {
|
class Connect extends Component {
|
||||||
state = {
|
state = {
|
||||||
showOptionals: false
|
showOptionals: false
|
||||||
@ -21,32 +18,35 @@ class Connect extends Component {
|
|||||||
|
|
||||||
handleSSLChange = e => {
|
handleSSLChange = e => {
|
||||||
const { values, setFieldValue } = this.props;
|
const { values, setFieldValue } = this.props;
|
||||||
if (e.target.checked && values.port === '6667') {
|
if (e.target.checked && values.port === 6667) {
|
||||||
setFieldValue('port', '6697', false);
|
setFieldValue('port', 6697, false);
|
||||||
} else if (!e.target.checked && values.port === '6697') {
|
} else if (!e.target.checked && values.port === 6697) {
|
||||||
setFieldValue('port', '6667', false);
|
setFieldValue('port', 6667, false);
|
||||||
}
|
}
|
||||||
setFieldValue('tls', e.target.checked);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleShowClick = () => {
|
handleShowClick = () => {
|
||||||
this.setState({ showOptionals: !this.state.showOptionals });
|
this.setState({ showOptionals: !this.state.showOptionals });
|
||||||
};
|
};
|
||||||
|
|
||||||
renderOptionals = () => {
|
renderOptionals = () => (
|
||||||
const { errors, touched } = this.props;
|
|
||||||
return (
|
|
||||||
<div>
|
<div>
|
||||||
<TextInput name="username" placeholder="Username" />
|
<TextInput name="username" placeholder="Username" />
|
||||||
{touched.username && <Error>{errors.username}</Error>}
|
{this.renderError('username')}
|
||||||
<TextInput type="password" name="password" placeholder="Password" />
|
<TextInput type="password" name="password" placeholder="Password" />
|
||||||
<TextInput name="realname" placeholder="Realname" />
|
<TextInput name="realname" placeholder="Realname" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
renderError = name => {
|
||||||
|
const { touched, errors } = this.props;
|
||||||
|
if (touched[name] && errors[name]) {
|
||||||
|
return <div className="form-error">{errors[name]}</div>;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { defaults, values, errors, touched } = this.props;
|
const { defaults, values } = this.props;
|
||||||
const { readonly, showDetails } = defaults;
|
const { readonly, showDetails } = defaults;
|
||||||
let form;
|
let form;
|
||||||
|
|
||||||
@ -65,8 +65,8 @@ class Connect extends Component {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<TextInput name="nick" placeholder="Nick" />
|
<TextInput name="nick" placeholder="Nick" />
|
||||||
{touched.nick && <Error>{errors.nick}</Error>}
|
{this.renderError('nick')}
|
||||||
<input type="submit" value="Connect" />
|
<button>Connect</button>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -76,18 +76,18 @@ class Connect extends Component {
|
|||||||
<TextInput name="name" placeholder="Name" />
|
<TextInput name="name" placeholder="Name" />
|
||||||
<div className="connect-form-address">
|
<div className="connect-form-address">
|
||||||
<TextInput name="host" placeholder="Host" />
|
<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} />
|
<Checkbox name="tls" label="SSL" onChange={this.handleSSLChange} />
|
||||||
</div>
|
</div>
|
||||||
{touched.host && <Error>{errors.host}</Error>}
|
{this.renderError('host')}
|
||||||
{touched.port && <Error>{errors.port}</Error>}
|
{this.renderError('port')}
|
||||||
<TextInput name="nick" placeholder="Nick" />
|
<TextInput name="nick" placeholder="Nick" />
|
||||||
{touched.nick && <Error>{errors.nick}</Error>}
|
{this.renderError('nick')}
|
||||||
<TextInput name="channels" placeholder="Channels" />
|
<TextInput name="channels" placeholder="Channels" />
|
||||||
{touched.channels && <Error>{errors.channels}</Error>}
|
{this.renderError('channels')}
|
||||||
{this.state.showOptionals && this.renderOptionals()}
|
{this.state.showOptionals && this.renderOptionals()}
|
||||||
<i className="icon-ellipsis" onClick={this.handleShowClick} />
|
<i className="icon-ellipsis" onClick={this.handleShowClick} />
|
||||||
<input type="submit" value="Connect" />
|
<button>Connect</button>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -103,11 +103,11 @@ class Connect extends Component {
|
|||||||
|
|
||||||
export default withFormik({
|
export default withFormik({
|
||||||
mapPropsToValues: ({ defaults }) => {
|
mapPropsToValues: ({ defaults }) => {
|
||||||
let port = '6667';
|
let port = 6667;
|
||||||
if (defaults.port) {
|
if (defaults.port) {
|
||||||
port = `${defaults.port}`;
|
({ port } = defaults);
|
||||||
} else if (defaults.ssl) {
|
} else if (defaults.ssl) {
|
||||||
port = '6697';
|
port = 6697;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -138,7 +138,7 @@ export default withFormik({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!values.port) {
|
if (!values.port) {
|
||||||
values.port = values.tls ? '6697' : '6667';
|
values.port = values.tls ? 6697 : 6667;
|
||||||
} else if (!isInt(values.port, 1, 65535)) {
|
} else if (!isInt(values.port, 1, 65535)) {
|
||||||
errors.port = 'Invalid port';
|
errors.port = 'Invalid port';
|
||||||
}
|
}
|
||||||
@ -178,6 +178,7 @@ export default withFormik({
|
|||||||
const channels = values.channels.split(',');
|
const channels = values.channels.split(',');
|
||||||
delete values.channels;
|
delete values.channels;
|
||||||
|
|
||||||
|
values.port = `${values.port}`;
|
||||||
connect(values);
|
connect(values);
|
||||||
select(values.host);
|
select(values.host);
|
||||||
|
|
||||||
|
@ -12,32 +12,31 @@ export default class Editable extends PureComponent {
|
|||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (this.state.editing && nextProps.value !== this.props.value) {
|
if (this.state.editing && nextProps.value !== this.props.value) {
|
||||||
this.setState({
|
this.updateInputWidth(nextProps.value);
|
||||||
width: this.getInputWidth(nextProps.value)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
if (!prevState.editing && this.state.editing) {
|
if (!prevState.editing && this.state.editing) {
|
||||||
// eslint-disable-next-line react/no-did-update-set-state
|
// eslint-disable-next-line react/no-did-update-set-state
|
||||||
this.setState({
|
this.updateInputWidth(this.props.value);
|
||||||
width: this.getInputWidth(this.props.value)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getInputWidth(value) {
|
updateInputWidth = value => {
|
||||||
if (this.input) {
|
if (this.input) {
|
||||||
const style = window.getComputedStyle(this.input);
|
const style = window.getComputedStyle(this.input);
|
||||||
const padding =
|
const padding = parseInt(style.paddingRight, 10);
|
||||||
parseInt(style.paddingLeft, 10) + parseInt(style.paddingRight, 10);
|
|
||||||
// Make sure the width is atleast 1px so the caret always shows
|
// Make sure the width is atleast 1px so the caret always shows
|
||||||
const width =
|
const width =
|
||||||
stringWidth(value, `${style.fontSize} ${style.fontFamily}`) || 1;
|
stringWidth(value, `${style.fontSize} ${style.fontFamily}`) || 1;
|
||||||
return padding + width;
|
|
||||||
}
|
this.setState({
|
||||||
|
width: width + padding * 2,
|
||||||
|
indent: padding
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
startEditing = () => {
|
startEditing = () => {
|
||||||
if (this.props.editable) {
|
if (this.props.editable) {
|
||||||
@ -84,7 +83,9 @@ export default class Editable extends PureComponent {
|
|||||||
const { children, className, value } = this.props;
|
const { children, className, value } = this.props;
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
width: this.state.width
|
width: this.state.width,
|
||||||
|
textIndent: this.state.indent,
|
||||||
|
paddingLeft: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.state.editing ? (
|
return this.state.editing ? (
|
||||||
|
@ -10,6 +10,9 @@ const TextInput = ({ name, placeholder, ...props }) => (
|
|||||||
className={field.value ? 'value' : null}
|
className={field.value ? 'value' : null}
|
||||||
type="text"
|
type="text"
|
||||||
name={name}
|
name={name}
|
||||||
|
autoCorrect="off"
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck="false"
|
||||||
{...field}
|
{...field}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { isChannel, isValidNick, isValidChannel, isValidUsername, isInt } from '..';
|
import { isChannel, isValidNick, isValidChannel, isValidUsername } from '..';
|
||||||
import linkify from '../linkify';
|
import linkify from '../linkify';
|
||||||
|
|
||||||
describe('isChannel()', () => {
|
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()', () => {
|
describe('linkify()', () => {
|
||||||
const proto = href => (href.indexOf('http') !== 0 ? `http://${href}` : href);
|
const proto = href => (href.indexOf('http') !== 0 ? `http://${href}` : href);
|
||||||
const linkTo = href => (
|
const linkTo = href => (
|
||||||
|
@ -122,18 +122,11 @@ export function isValidUsername(username) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isInt(str, min, max) {
|
export function isInt(i, min, max) {
|
||||||
if (!str || str < min || str > max) {
|
if (i < min || i > max || Math.floor(i) !== i) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < str.length; i++) {
|
|
||||||
const char = str.charCodeAt(i);
|
|
||||||
if (char < 48 || char > 57) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user