mirror of
https://github.com/urbit/shrub.git
synced 2024-12-16 14:58:25 +03:00
removed unrelated leftover files of repo initialization from chat
This commit is contained in:
parent
f0e04f3076
commit
949fbfba0d
@ -1,164 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Scrollbars } from 'react-custom-scrollbars';
|
||||
import classnames from 'classnames';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { Message } from '/components/lib/message';
|
||||
import { ChatHeader } from '/components/lib/chat-header';
|
||||
import { ChatInput } from '/components/lib/chat-input';
|
||||
|
||||
import { prettyShip, getMessageContent, isDMStation } from '/lib/util';
|
||||
|
||||
export class ChatScreen extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
station: props.match.params.ship + "/" + props.match.params.station,
|
||||
circle: props.match.params.station,
|
||||
host: props.match.params.ship,
|
||||
message: "",
|
||||
pendingMessages: [],
|
||||
numPeople: 0
|
||||
};
|
||||
|
||||
|
||||
this.onScrollStop = this.onScrollStop.bind(this);
|
||||
this.buildMessage = this.buildMessage.bind(this);
|
||||
this.setPendingMessage = this.setPendingMessage.bind(this);
|
||||
|
||||
this.scrollbarRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (isDMStation(this.state.station)) {
|
||||
let cir = this.state.station.split("/")[1];
|
||||
this.props.api.hall({
|
||||
newdm: {
|
||||
sis: cir.split(".")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.scrollIfLocked();
|
||||
this.updateNumPeople();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { props } = this;
|
||||
if ((props.match.params.ship != prevProps.match.params.ship) ||
|
||||
(props.match.params.station != prevProps.match.params.station)) {
|
||||
this.setState({
|
||||
station: props.match.params.ship + "/" + props.match.params.station,
|
||||
circle: props.match.params.station,
|
||||
host: props.match.params.ship,
|
||||
message: "",
|
||||
pendingMessages: [],
|
||||
numPeople: 0
|
||||
});
|
||||
}
|
||||
|
||||
this.updateNumPeople();
|
||||
this.updateNumMessagesLoaded(prevProps, prevState);
|
||||
}
|
||||
|
||||
updateNumPeople() {
|
||||
let conf = this.props.configs[this.state.station] || {};
|
||||
let sis = _.get(conf, 'con.sis');
|
||||
let numPeople = !!sis ? sis.length : 0;
|
||||
if (numPeople !== this.state.numPeople) {
|
||||
this.setState({ numPeople });
|
||||
}
|
||||
}
|
||||
|
||||
updateNumMessagesLoaded(prevProps, prevState) {
|
||||
let station = prevProps.store.messages.stations[this.state.station] || [];
|
||||
let numMessages = station.length;
|
||||
|
||||
if (numMessages > prevState.numMessages && this.scrollbarRef.current) {
|
||||
this.setState({
|
||||
numMessages: numMessages
|
||||
});
|
||||
|
||||
this.scrollIfLocked();
|
||||
}
|
||||
}
|
||||
|
||||
scrollIfLocked() {
|
||||
if (this.state.scrollLocked && this.scrollbarRef.current) {
|
||||
this.scrollbarRef.current.scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
onScrollStop() {
|
||||
let scroll = this.scrollbarRef.current.getValues();
|
||||
|
||||
this.setState({
|
||||
scrollLocked: (scroll.top === 1)
|
||||
});
|
||||
|
||||
if (scroll.top === 0) {
|
||||
this.requestChatBatch();
|
||||
}
|
||||
}
|
||||
|
||||
setPendingMessage(message) {
|
||||
this.setState({
|
||||
pendingMessages: this.state.pendingMessages.concat({...message, pending: true})
|
||||
});
|
||||
}
|
||||
|
||||
buildMessage(msg) {
|
||||
let details = msg.printship ? null : getMessageContent(msg);
|
||||
|
||||
if (msg.printship) {
|
||||
return (
|
||||
<a
|
||||
className="vanilla hoverline text-600 text-mono"
|
||||
href={prettyShip(msg.aut)[1]}>
|
||||
{prettyShip(`~${msg.aut}`)[0]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Message msg={msg} details={details} />
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
let messages = this.props.store.messages.stations[this.state.station] || [];
|
||||
messages = [...messages, ...this.state.pendingMessages];
|
||||
|
||||
let chatMessages = messages.map(this.buildMessage);
|
||||
|
||||
return (
|
||||
<div className="h-100 w-100 overflow-x-hidden flex flex-column">
|
||||
<div style={{ flexBasis:72 }}>
|
||||
<ChatHeader title={this.state.circle} numPeople={this.state.numPeople} />
|
||||
</div>
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<Scrollbars
|
||||
ref={this.scrollbarRef}
|
||||
renderTrackHorizontal={props => <div style={{display: "none"}}/>}
|
||||
onScrollStop={this.onScrollStop}
|
||||
renderView={props => <div {...props} />}
|
||||
style={{ height: '100%' }}
|
||||
autoHide>
|
||||
{chatMessages}
|
||||
</Scrollbars>
|
||||
</div>
|
||||
<div style={{ flexBasis:112 }}>
|
||||
<ChatInput
|
||||
api={this.props.api}
|
||||
store={this.props.store}
|
||||
station={this.state.station}
|
||||
circle={this.state.circle}
|
||||
scrollbarRef={this.scrollbarRef}
|
||||
setPendingMessage={this.setPendingMessage}
|
||||
placeholder='Message...' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
export class CollectionItem extends Component {
|
||||
|
||||
onClick() {
|
||||
const { props } = this;
|
||||
console.log("collection-item clicked!");
|
||||
// props.history.push(props.url);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
|
||||
let selectedCss = !!props.selected ? 'bg-light-gray' : 'bg-white pointer';
|
||||
return (
|
||||
<div className={'pa3 ' + selectedCss} onClick={this.onClick.bind(this)}>
|
||||
<div className='w-100 v-mid'>
|
||||
<h3 className='w-60 dib sans-serif'>{props.title}</h3>
|
||||
<p className='w-40 tr dib sans-serif gray'>{props.datetime}</p>
|
||||
</div>
|
||||
<p className='pt2 sans-serif gray'>{props.description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
|
||||
export class CollectionList extends Component {
|
||||
render() {
|
||||
console.log("collection-list.props", this.props);
|
||||
|
||||
let listItems = this.props.list.map((coll) => {
|
||||
return (
|
||||
<p className="w-100">
|
||||
{coll.data.info.title}
|
||||
</p>
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
console.log(listItems);
|
||||
|
||||
return (
|
||||
<div className="w-100">
|
||||
{listItems}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import { Sigil } from '/components/lib/icons/sigil';
|
||||
import { isUrl, uuid, isDMStation } from '/lib/util';
|
||||
|
||||
|
||||
export class ChatHeader extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="w-100 pa2 mb3 cf">
|
||||
<div className="fl">
|
||||
<p className="f3 sans-serif">{this.props.title}</p>
|
||||
<div>
|
||||
<p className="dib mid-gray mr2 sans-serif">{this.props.numPeople} Participants</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fr">
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import { Sigil } from '/components/lib/icons/sigil';
|
||||
import { isUrl, uuid, isDMStation } from '/lib/util';
|
||||
|
||||
|
||||
export class ChatInput extends Component {
|
||||
|
||||
/*
|
||||
Props:
|
||||
- station
|
||||
- api
|
||||
- store
|
||||
- circle
|
||||
- placeholder
|
||||
- setPendingMessage
|
||||
- scrollbarRef
|
||||
*/
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
message: ""
|
||||
};
|
||||
|
||||
this.textareaRef = React.createRef();
|
||||
|
||||
this.messageSubmit = this.messageSubmit.bind(this);
|
||||
this.messageChange = this.messageChange.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.bindShortcuts();
|
||||
}
|
||||
|
||||
bindShortcuts() {
|
||||
Mousetrap(this.textareaRef.current).bind('enter', e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.messageSubmit(e);
|
||||
});
|
||||
}
|
||||
|
||||
messageChange(event) {
|
||||
this.setState({message: event.target.value});
|
||||
}
|
||||
|
||||
messageSubmit() {
|
||||
let aud, sep;
|
||||
let wen = Date.now();
|
||||
let uid = uuid();
|
||||
let aut = window.ship;
|
||||
|
||||
let config = this.props.store.configs[this.state.station];
|
||||
|
||||
if (isDMStation(this.props.station)) {
|
||||
aud = this.props.station
|
||||
.split("/")[1]
|
||||
.split(".")
|
||||
.map((mem) => `~${mem}/${this.props.circle}`);
|
||||
|
||||
} else {
|
||||
aud = [this.props.station];
|
||||
}
|
||||
|
||||
if (isUrl(this.state.message)) {
|
||||
sep = {
|
||||
url: this.state.message
|
||||
}
|
||||
} else {
|
||||
sep = {
|
||||
lin: {
|
||||
msg: this.state.message,
|
||||
pat: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let message = {
|
||||
uid,
|
||||
aut,
|
||||
wen,
|
||||
aud,
|
||||
sep,
|
||||
};
|
||||
|
||||
this.props.api.hall({
|
||||
convey: [message]
|
||||
});
|
||||
|
||||
this.props.setPendingMessage(message);
|
||||
|
||||
console.log('ending message submit');
|
||||
|
||||
this.setState({
|
||||
message: ""
|
||||
});
|
||||
|
||||
// TODO: Push to end of event queue to let pendingMessages render before scrolling
|
||||
// There's probably a better way to do this
|
||||
setTimeout(() => {
|
||||
if (this.props.scrollbarRef.current) this.props.scrollbarRef.current.scrollToBottom();
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="w-100 pa2 mb3 cf flex">
|
||||
<div className="fl mr2" style={{ flexBasis: 48 }}>
|
||||
<Sigil ship={window.ship} size={44} />
|
||||
</div>
|
||||
<div className="fr" style={{ flexGrow: 1, border: "2px solid #e6e6e6" }}>
|
||||
<textarea className="w-100 h-100 bn sans-serif pa2"
|
||||
style={{
|
||||
resize: "none"
|
||||
}}
|
||||
ref={this.textareaRef}
|
||||
placeholder={this.props.placeholder}
|
||||
value={this.state.message}
|
||||
onChange={this.messageChange} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { getStationDetails } from '/services';
|
||||
|
||||
export class ChatList extends Component {
|
||||
componentDidMount() {
|
||||
let path = `/public`;
|
||||
|
||||
this.props.api.bind(path, "PUT", this.props.hostship.slice(1));
|
||||
}
|
||||
|
||||
renderChats() {
|
||||
if (this.props.store.public[this.props.hostship]) {
|
||||
const chats = this.props.store.public[this.props.hostship].map((cir) => {
|
||||
const deets = getStationDetails(cir)
|
||||
if (deets.type == "stream-chat" || deets.type == "stream-dm") {
|
||||
return (
|
||||
<div className="mt-2 text-500">
|
||||
<a href={`/~chat/{cir}`}>{cir}</a>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return chats;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const chats = this.renderChats();
|
||||
return (
|
||||
<div>
|
||||
<div className="text-600 mt-8">Chats</div>
|
||||
{chats}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { isDMStation, getMessageContent } from '/lib/util';
|
||||
import { Sigil } from '/components/lib/icons/sigil';
|
||||
import classnames from 'classnames';
|
||||
import moment from 'moment';
|
||||
|
||||
export class Message extends Component {
|
||||
buildPostTitle(messageDetails) {
|
||||
if (messageDetails.postUrl) {
|
||||
return (
|
||||
<a className="pr-12 text-600 underline"
|
||||
href={messageDetails.postUrl}>
|
||||
{messageDetails.postTitle}
|
||||
</a>
|
||||
)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
renderContent(type) {
|
||||
if (type === "text") {
|
||||
return this.buildPostTitle(this.props.details);
|
||||
} else if (type === "url") {
|
||||
if (/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF)$/.exec(this.props.details.content)) {
|
||||
return (
|
||||
<img src={this.props.details.content} style={{width:"30%"}}></img>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<a href={this.props.details.content} target="_blank">{this.props.details.content}</a>
|
||||
)
|
||||
}
|
||||
} else if (type === "exp") {
|
||||
return (
|
||||
<div className="text-body">
|
||||
<div className="text-mono">{this.props.details.content}</div>
|
||||
<pre className="text-mono mt-0">{this.props.details.res}</pre>
|
||||
</div>
|
||||
)
|
||||
} else if (['new item', 'edited item'].includes(type)) {
|
||||
return <span className="text-body" dangerouslySetInnerHTML={{__html: this.props.details.snip}}></span>
|
||||
} else if (type === "lin") {
|
||||
return (
|
||||
<p className="sans-serif">{this.props.details.content}</p>
|
||||
);
|
||||
} else {
|
||||
return <span className="text-mono">{'<unknown message type>'}</span>;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="w-100 pa2 mb3 cf flex">
|
||||
<div className="fl mr2">
|
||||
<Sigil ship={this.props.msg.aut} size={44} />
|
||||
</div>
|
||||
<div className="fr" style={{ flexGrow: 1 }}>
|
||||
<div className="mb2">
|
||||
<p className="sans-serif gray dib mr2">~{this.props.msg.aut}</p>
|
||||
<p className="sans-serif gray dib">{moment.unix(this.props.msg.wen).format('hh:mm')}</p>
|
||||
</div>
|
||||
{this.renderContent(this.props.details.type)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
export class SidebarItem extends Component {
|
||||
|
||||
onClick() {
|
||||
const { props } = this;
|
||||
props.history.push('/~chat/' + props.title);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
|
||||
let selectedCss = !!props.selected ? 'bg-light-gray' : 'bg-white pointer';
|
||||
return (
|
||||
<div className={'pa3 ' + selectedCss} onClick={this.onClick.bind(this)}>
|
||||
<div className='w-100 v-mid'>
|
||||
<h3 className='w-60 dib sans-serif'>{props.title}</h3>
|
||||
<p className='w-40 tr dib sans-serif gray'>{props.datetime}</p>
|
||||
</div>
|
||||
<p className='pt2 sans-serif gray'>{props.description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { Scrollbars } from 'react-custom-scrollbars';
|
||||
import moment from 'moment';
|
||||
|
||||
import { getMessageContent } from '/lib/util';
|
||||
import { SidebarItem } from '/components/sidebar-item';
|
||||
|
||||
export class Sidebar extends Component {
|
||||
render() {
|
||||
const { props } = this;
|
||||
let station = props.match.params.ship + '/' + props.match.params.station;
|
||||
|
||||
let sidebarItems = props.circles.map((cir) => {
|
||||
let msg = props.messagePreviews[cir];
|
||||
let parsed = getMessageContent(msg);
|
||||
let wen = moment.unix(msg.wen / 1000).from(moment.utc());
|
||||
|
||||
return (
|
||||
<CollectionItem
|
||||
title={cir}
|
||||
description={parsed.content}
|
||||
datetime={wen}
|
||||
selected={station === cir}
|
||||
history={props.history}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
<div className="h-100 w-100 overflow-x-hidden flex flex-column">
|
||||
<div className="pl3 pr3 pt2 pb2 cf">
|
||||
<h2 className="dib lh-title sans-serif w-50 f2">Publish</h2>
|
||||
<a className="dib tr lh-title sans-serif w-50 f4 underline">+ New</a>
|
||||
</div>
|
||||
<div className='mt2 pl3 pr3 mb2 w-100'>
|
||||
<div>My Collections</div>
|
||||
</div>
|
||||
<div style={{ flexGrow: 1 }}>
|
||||
<Scrollbars
|
||||
ref={this.scrollbarRef}
|
||||
renderTrackHorizontal={props => <div style={{display: "none"}}/>}
|
||||
onScrollStop={this.onScrollStop}
|
||||
renderView={props => <div {...props} />}
|
||||
style={{ height: '100%' }}
|
||||
autoHide>
|
||||
{sidebarItems}
|
||||
</Scrollbars>
|
||||
</div>
|
||||
<div className='mt2 pl3 pr3 mb2 w-100'>
|
||||
<div>My Subscriptions</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
|
||||
export class Skeleton extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="cf h-100 w-100 absolute flex">
|
||||
<div className="fl h-100 br overflow-x-hidden" style={{ flexBasis: 320 }}>
|
||||
{this.props.sidebar}
|
||||
</div>
|
||||
<div className="h-100 fr" style={{ flexGrow: 1 }}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user