chat: refactored join page into indigo

This commit is contained in:
Logan Allen 2020-08-17 11:35:38 -07:00
parent 80b3d59789
commit 79732ddad3
3 changed files with 108 additions and 119 deletions

View File

@ -4802,6 +4802,11 @@
}
}
},
"fn-name": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/fn-name/-/fn-name-3.0.0.tgz",
"integrity": "sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA=="
},
"follow-redirects": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz",
@ -7450,6 +7455,11 @@
"react-is": "^16.8.1"
}
},
"property-expr": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.3.tgz",
"integrity": "sha512-TEMKBo6s4gZUKmNYwaMkS2JdDxdWgUijW/U/jLAOHVyLZfU1KHXv+mC1J9gkfGOr8532XHqMJytko1lSjc0kmw=="
},
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@ -9070,6 +9080,11 @@
"xml-reader": "2.4.3"
}
},
"synchronous-promise": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.13.tgz",
"integrity": "sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA=="
},
"tabbable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz",
@ -9302,6 +9317,11 @@
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
"dev": true
},
"toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
},
"transformation-matrix": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/transformation-matrix/-/transformation-matrix-2.1.1.tgz",
@ -11885,6 +11905,20 @@
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
},
"yup": {
"version": "0.29.3",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.29.3.tgz",
"integrity": "sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ==",
"requires": {
"@babel/runtime": "^7.10.5",
"fn-name": "~3.0.0",
"lodash": "^4.17.15",
"lodash-es": "^4.17.11",
"property-expr": "^2.0.2",
"synchronous-promise": "^2.0.13",
"toposort": "^2.0.2"
}
}
}
}

View File

@ -32,7 +32,8 @@
"styled-system": "^5.1.5",
"suncalc": "^1.8.0",
"urbit-ob": "^5.0.0",
"urbit-sigil-js": "^1.3.2"
"urbit-sigil-js": "^1.3.2",
"yup": "^0.29.3"
},
"devDependencies": {
"@babel/core": "^7.9.0",

View File

@ -1,146 +1,100 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Spinner } from '~/views/components/Spinner';
import { Spinner } from '../../../components/Spinner';
import urbitOb from 'urbit-ob';
import { Box, Text, Input, Button } from '@tlon/indigo-react';
import { Formik, Form } from 'formik'
import * as Yup from 'yup';
const schema = Yup.object().shape({
station: Yup.string()
.lowercase()
.trim()
.test('is-station',
'Chat must have a valid name',
(val) =>
val &&
val.split('/').length === 2 &&
urbitOb.isValidPatp(val.split('/')[0])
)
.required('Required')
});
export class JoinScreen extends Component {
constructor(props) {
super(props);
this.state = {
station: '/',
error: false,
awaiting: false
};
this.stationChange = this.stationChange.bind(this);
}
componentDidMount() {
this.componentDidUpdate();
if (this.props.station) {
this.onSubmit({ station: this.props.station });
}
}
componentDidUpdate(prevProps, prevState) {
const { props, state } = this;
if ((props.autoJoin !== '/undefined/undefined') &&
(props.api && (prevProps?.api !== props.api))) {
let station = props.autoJoin.split('/');
const ship = station[1];
if (
station.length < 2 ||
!urbitOb.isValidPatp(ship)
) {
this.setState({
error: true
});
onSubmit(values) {
console.log(values);
this.setState({ awaiting: true }, () => {
console.log(values);
const station = values.station.trim();
if (`/${station}` in this.props.chatSynced) {
this.props.history.push(`/~chat/room/${station}`);
return;
}
station = props.autoJoin;
this.setState({
station,
awaiting: true
}, () => props.api.chat.join(ship, station, true));
}
if (state.station in props.inbox ||
(props?.chatSynced !== prevProps?.chatSynced && state.station !== '/')) {
this.setState({ awaiting: false });
props.history.push(`/~chat/room${state.station}`);
}
}
onClickJoin() {
const { props, state } = this;
let station = state.station.split('/');
const ship = station[1];
if (
station.length < 2 ||
!urbitOb.isValidPatp(ship)
) {
this.setState({
error: true
});
return;
}
station = state.station.trim();
this.setState({
station,
awaiting: true
}, () => {
props.api.chat.join(ship, station, true);
});
}
stationChange(event) {
this.setState({
station: `/${event.target.value.trim()}`
props.api.chat.join(ship, station, true)
this.props.history.push(`/~chat/room/${station}`);
});
}
render() {
const { state } = this;
let joinClasses = 'db f9 green2 ba pa2 b--green2 bg-gray0-d pointer';
if ((!state.station) || (state.station === '/')) {
joinClasses = 'db f9 gray2 ba pa2 b--gray3 bg-gray0-d pointer';
}
let errElem = (<span />);
if (state.error) {
errElem = (
<span className="f9 inter red2 db">
Chat must have a valid name.
</span>
);
}
const { props, state } = this;
return (
<div className={`h-100 w-100 pa3 pt2 overflow-x-hidden flex flex-column
bg-gray0-d white-d`}
>
<div
className="w-100 dn-m dn-l dn-xl inter pt1 pb6 f8"
>
<Link to="/~chat/">{'⟵ All Chats'}</Link>
</div>
<h2 className="mb3 f8">Join Existing Chat</h2>
<div className="w-100">
<p className="f8 lh-copy mt3 db">Enter a <span className="mono">~ship/chat-name</span></p>
<p className="f9 gray2 mb4">Chat names use lowercase, hyphens, and slashes.</p>
<textarea
ref={ (e) => {
this.textarea = e;
} }
className={'f7 mono ba bg-gray0-d white-d pa3 mb2 db ' +
'focus-b--black focus-b--white-d b--gray3 b--gray2-d'}
placeholder="~zod/chatroom"
spellCheck="false"
rows={1}
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.onClickJoin();
}
}}
style={{
resize: 'none'
}}
onChange={this.stationChange}
/>
{errElem}
<br />
<button
onClick={this.onClickJoin.bind(this)}
className={joinClasses}
>Join Chat</button>
<Spinner awaiting={this.state.awaiting} classes="mt4" text="Joining chat..." />
</div>
</div>
<Formik
enableReinitialize={true}
initialValues={{ station: props.station }}
validationSchema={schema}
onSubmit={this.onSubmit.bind(this)}>
<Form>
<Box width="100%" height="100%" p={3} overflowX="hidden">
<Box
width="100%"
pt={1} pb={5}
display={['', 'none', 'none', 'none']}
fontSize={0}>
<Link to="/~chat/">{'⟵ All Chats'}</Link>
</Box>
<Text mb={3} fontSize={0}>Join Existing Chat</Text>
<Box width="100%" maxWidth={350}>
<Box mt={3} mb={3} display="block">
<Text display="inline" fontSize={0}>
Enter a{' '}
</Text>
<Text display="inline" fontSize={0} fontFamily="mono">
~ship/chat-name
</Text>
</Box>
<Input
mt={4}
id="station"
placeholder="~zod/chatroom"
fontFamily="mono"
caption="Chat names use lowercase, hyphens, and slashes." />
<Button>Join Chat</Button>
<Spinner
awaiting={this.state.awaiting}
classes="mt4"
text="Joining chat..." />
</Box>
</Box>
</Form>
</Formik>
);
}
}