chat-js: added invite functionality

This commit is contained in:
Logan Allen 2019-10-31 11:39:11 -07:00
parent 40b6579873
commit cb158310e3
10 changed files with 93 additions and 35 deletions

File diff suppressed because one or more lines are too long

View File

@ -25,6 +25,12 @@ class UrbitApi {
delete: this.chatViewDelete.bind(this),
join: this.chatViewJoin.bind(this),
};
this.invite = {
accept: this.inviteAccept.bind(this),
decline: this.inviteDecline.bind(this),
invite: this.inviteInvite.bind(this)
};
}
bind(path, method, ship = this.authTokens.ship, app, success, fail, quit) {
@ -138,6 +144,46 @@ class UrbitApi {
this.chatViewAction({ join: { ship, path } });
}
inviteAction(data) {
this.action("invite-store", "json", data);
}
inviteInvite(path, ship) {
this.action("invite-hook", "json",
{
invite: {
path: '/chat',
invite: {
path,
ship: `~${window.ship}`,
recipient: ship,
app: 'chat-hook',
text: `You have been invited to /${window.ship}${path}`,
},
uid: uuid()
}
}
);
}
inviteAccept(uid) {
this.inviteAction({
accept: {
path: '/chat',
uid
}
});
}
inviteDecline(uid) {
this.inviteAction({
decline: {
path: '/chat',
uid
}
});
}
}
export let api = new UrbitApi();

View File

@ -52,6 +52,11 @@ export class InviteElement extends Component {
members: ''
}, () => {
props.api.groups.add(aud, props.path);
if (props.permissions.kind === 'white') {
aud.forEach((ship) => {
props.api.invite.invite(props.station, ship);
});
}
});
}

View File

@ -4,20 +4,17 @@ import _ from 'lodash';
export class SidebarInvite extends Component {
onAccept() {
this.props.api.invite.accept(this.props.uid);
}
onDecline() {
this.props.api.invite.decline(this.props.uid);
}
render() {
const { props } = this;
let cir = _.get(props, 'msg.sep.inv.cir', false);
let aut = _.get(props, 'msg.aut', false);
if (!aut || !cir || !props.config) {
return (
<div></div>
);
}
cir = cir.split('/')[1];
return (
<div className='pa3'>
<div className='w-100 v-mid'>
@ -26,17 +23,12 @@ export class SidebarInvite extends Component {
width: 12,
height: 12
}}></div>
<p className="dib body-regular fw-normal">Invite to&nbsp;
<span className='fw-bold'>
{cir}
</span>
<p className="dib body-regular fw-normal">
{props.invite.text}
</p>
</div>
<div className="w-100">
<p className='dib gray label-small-mono'>Hosted by {aut}</p>
</div>
<a className="dib w-50 pointer btn-font nice-green underline" onClick={this.onAccept.bind(this)}>Accept</a>
<a className="dib w-50 tr pointer btn-font nice-red underline" onClick={this.onReject.bind(this)}>Reject</a>
<a className="dib w-50 tr pointer btn-font nice-red underline" onClick={this.onDecline.bind(this)}>Decline</a>
</div>
)
}

View File

@ -93,7 +93,7 @@ export class MemberScreen extends Component {
{ window.ship === deSig(props.match.params.ship) ? (
<InviteElement
path={`/chat${state.station}/write`}
station={state.station}
station={`/${props.match.params.station}`}
permissions={props.write}
api={props.api} />
) : null }
@ -111,6 +111,7 @@ export class MemberScreen extends Component {
{ window.ship === deSig(props.match.params.ship) ?
( <InviteElement
path={`/chat${state.station}/read`}
station={`/${props.match.params.station}`}
permissions={props.read}
api={props.api}/>
) : null

View File

@ -68,7 +68,6 @@ export class NewScreen extends Component {
return;
}
// TODO: send invites
let aud = [];
let isValid = true;
if (state.invites.length > 2) {
@ -123,6 +122,11 @@ export class NewScreen extends Component {
}, () => {
props.setSpinner(true);
props.api.chatView.create(station, state.security, readAud, writeAud);
aud.forEach((ship) => {
if (ship !== `~${window.ship}`) {
props.api.invite.invite(station, ship);
}
});
});
}

View File

@ -47,16 +47,16 @@ export class Root extends Component {
unreads[stat] = envelopes.length > state.inbox[stat].config.read;
});
let inviteConfig = false;
let invites = '/chat' in state.invites ?
state.invites['/chat'] : {};
const renderChannelSidebar = (props) => (
<Sidebar
inbox={state.inbox}
messagePreviews={messagePreviews}
invites={[]}
invites={invites}
unreads={unreads}
api={api}
inviteConfig={inviteConfig}
{...props}
/>
);

View File

@ -3,18 +3,12 @@ import { Link } from "react-router-dom";
import classnames from 'classnames';
import _ from 'lodash';
import { SidebarInvite } from '/components/lib/sidebar-invite';
import { SidebarItem } from '/components/lib/sidebar-item';
export class Sidebar extends Component {
componentWillUnmount() {
if (this.setInvitesToReadInterval) {
clearInterval(this.setInvitesToReadInterval);
this.setInvitesToReadInterval = null;
}
}
onClickNew() {
this.props.history.push('/~chat/new');
}
@ -23,6 +17,16 @@ export class Sidebar extends Component {
const { props, state } = this;
let station = `/${props.match.params.ship}/${props.match.params.station}`;
let sidebarInvites = Object.keys(props.invites)
.map((uid) => {
return (
<SidebarInvite
uid={uid}
invite={props.invites[uid]}
api={props.api} />
);
});
let sidebarItems = Object.keys(props.inbox)
.map((box) => {
let msg = props.messagePreviews[box];
@ -73,6 +77,7 @@ export class Sidebar extends Component {
<div className="overflow-y-auto" style={{
height: 'calc(100vh - 60px - 48px)'
}}>
{sidebarInvites}
{sidebarItems}
</div>
</div>

View File

@ -8,7 +8,7 @@ export class InviteUpdateReducer {
this.create(data, state);
this.delete(data, state);
this.invite(data, state);
this.accept(data, state);
this.accepted(data, state);
this.decline(data, state);
}
}
@ -34,9 +34,10 @@ export class InviteUpdateReducer {
}
}
accept(json, state) {
let data = _.get(json, 'accept', false);
accepted(json, state) {
let data = _.get(json, 'accepted', false);
if (data) {
console.log(data);
delete state.invites[data.path][data.uid];
}
}

View File

@ -18,6 +18,10 @@ export class Subscription {
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/primary', 'PUT', api.authTokens.ship, 'invite-view',
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/all', 'PUT', api.authTokens.ship, 'group-store',
this.handleEvent.bind(this),
this.handleError.bind(this),