Merge pull request #2616 from urbit/two-round

chat-js: improve subscription speed by doing two rounds of subscriptions and no longer subscribing to groups
This commit is contained in:
ixv 2020-03-30 17:48:39 -07:00 committed by GitHub
commit 8f1655171d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 52 additions and 189 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -224,7 +224,7 @@ export class ChatScreen extends Component {
);
});
let group = Array.from(props.group.values());
let group = Array.from(props.permission.who.values());
const isinPopout = props.popout ? "popout/" : "";
@ -301,7 +301,6 @@ export class ChatScreen extends Component {
station={props.station}
owner={deSig(props.match.params.ship)}
ownerContact={ownerContact}
permissions={props.permissions}
envelopes={props.envelopes}
contacts={props.contacts}
placeholder="Message..."

View File

@ -422,36 +422,7 @@ export class ChatInput extends Component {
});
}
readOnlyRender() {
const { props } = this;
let color = !!props.ownerContact
? uxToHex(props.ownerContact.color) : '000000';
let sigilClass = !!props.ownerContact
? "" : "mix-blend-diff";
return (
<div className="pa3 cf flex black bt b--gray4 o-50">
<div className="fl" style={{
marginTop: 4,
flexBasis: 24,
height: 24
}}>
<Sigil
ship={window.ship}
size={24}
color={`#${color}`}
classes={sigilClass}
/>
</div>
<div className="fr h-100 flex" style={{ flexGrow: 1, height: 28, paddingTop: 6, resize: "none" }}>
<p className="pl3">This chat is read only and you cannot post.</p>
</div>
</div>
);
}
writeAccessRender() {
render() {
const { props, state } = this;
let color = !!props.ownerContact
@ -505,29 +476,4 @@ export class ChatInput extends Component {
</div>
);
}
render() {
const { props, state } = this;
let writePermission = props.permissions[`/chat${props.station}/write`];
if (writePermission) {
if (writePermission.kind === 'black') {
// black
if (writePermission.who.has(window.ship)) {
return this.readOnlyRender();
} else {
return this.writeAccessRender();
}
} else if (writePermission.kind === 'white') {
// white
if (writePermission.who.has(window.ship)) {
return this.writeAccessRender();
} else {
return this.readOnlyRender();
}
}
} else {
return this.writeAccessRender();
}
}
}

View File

@ -49,6 +49,7 @@ export class InviteSearch extends Component {
let peers = [],
peerSet = new Set(),
contacts = new Map;
Object.keys(this.props.groups).map(group => {
if (this.props.groups[group].size > 0) {
let groupEntries = this.props.groups[group].values();
@ -56,6 +57,7 @@ export class InviteSearch extends Component {
peerSet.add(member);
}
}
if (this.props.contacts[group]) {
let groupEntries = this.props.groups[group].values();
for (let member of groupEntries) {

View File

@ -216,6 +216,11 @@ export class NewScreen extends Component {
);
}
let groups = {};
Object.keys(props.permissions).forEach((pem) => {
groups[pem] = props.permissions[pem].who;
});
return (
<div
className={
@ -259,7 +264,7 @@ export class NewScreen extends Component {
Selected groups or ships will be able to post to chat
</p>
<InviteSearch
groups={props.groups}
groups={groups}
contacts={props.contacts}
associations={props.associations}
groupResults={true}

View File

@ -99,7 +99,7 @@ export class Root extends Component {
<NewScreen
api={api}
inbox={state.inbox || {}}
groups={state.groups || {}}
permissions={state.permissions || {}}
contacts={state.contacts || {}}
associations={associations.contacts}
{...props}
@ -119,7 +119,6 @@ export class Root extends Component {
station = '/~' + station;
}
return (
<Skeleton
spinner={state.spinner}
@ -168,8 +167,11 @@ export class Root extends Component {
let association =
station in associations["chat"] ? associations.chat[station] : {};
let group = state.groups[station] || new Set([]);
let permission =
station in state.permissions ? state.permissions[station] : {
who: new Set([]),
kind: 'white'
};
let popout = props.match.url.includes("/popout/");
return (
@ -190,9 +192,8 @@ export class Root extends Component {
length={mailbox.config.length}
envelopes={mailbox.envelopes}
inbox={state.inbox}
group={group}
contacts={roomContacts}
permissions={state.permissions}
permission={permission}
pendingMessages={state.pendingMessages}
popout={popout}
sidebarShown={state.sidebarShown}
@ -255,7 +256,6 @@ export class Root extends Component {
if (sig) {
station = '/~' + station;
}
let group = state.groups[station] || new Set([]);
let popout = props.match.url.includes("/popout/");
@ -280,12 +280,11 @@ export class Root extends Component {
station={station}
association={association}
permission={permission}
groups={state.groups || {}}
permissions={state.permissions || {}}
contacts={state.contacts || {}}
associations={associations.contacts}
api={api}
station={station}
group={group}
inbox={state.inbox}
popout={popout}
sidebarShown={state.sidebarShown}

View File

@ -223,7 +223,7 @@ export class SettingsScreen extends Component {
group to add this chat to.
</p>
<InviteSearch
groups={props.groups}
permissions={props.permissions}
contacts={props.contacts}
associations={props.associations}
groupResults={true}
@ -340,7 +340,7 @@ export class SettingsScreen extends Component {
const { props, state } = this;
const isinPopout = this.props.popout ? "popout/" : "";
let writeGroup = Array.from(props.group.values());
let permission = Array.from(props.permission.who.values());
if (!!state.isLoading) {
let text = state.loadingText || 'Working...';
@ -378,7 +378,7 @@ export class SettingsScreen extends Component {
<ChatTabBar
{...props}
station={props.station}
numPeers={writeGroup.length}
numPeers={permission.length}
host={props.match.params.ship}
api={props.api}
/>
@ -423,7 +423,7 @@ export class SettingsScreen extends Component {
<ChatTabBar
{...props}
station={props.station}
numPeers={writeGroup.length}
numPeers={permission.length}
isOwner={deSig(props.match.params.ship) === window.ship}
popout={this.props.popout}
/>

View File

@ -1,65 +0,0 @@
import _ from 'lodash';
export class GroupUpdateReducer {
reduce(json, state) {
let data = _.get(json, 'group-update', false);
if (data) {
this.add(data, state);
this.remove(data, state);
this.bundle(data, state);
this.unbundle(data, state);
this.keys(data, state);
this.path(data, state);
}
}
add(json, state) {
let data = _.get(json, 'add', false);
if (data) {
for (let member of data.members) {
state.groups[data.path].add(member);
}
}
}
remove(json, state) {
let data = _.get(json, 'remove', false);
if (data) {
for (let member of data.members) {
state.groups[data.path].delete(member);
}
}
}
bundle(json, state) {
let data = _.get(json, 'bundle', false);
if (data) {
state.groups[data.path] = new Set();
}
}
unbundle(json, state) {
let data = _.get(json, 'unbundle', false);
if (data) {
delete state.groups[data.path];
}
}
keys(json, state) {
let data = _.get(json, 'keys', false);
if (data) {
state.groupKeys = new Set(data.keys);
}
}
path(json, state) {
let data = _.get(json, 'path', false);
if (data) {
state.groups[data.path] = new Set([data.members]);
}
}
}

View File

@ -9,13 +9,6 @@ export class InitialReducer {
state.chatInitialized = true;
}
data = _.get(json, 'group-initial', false);
if (data) {
for (let group in data) {
state.groups[group] = new Set(data[group]);
}
}
data = _.get(json, 'permission-initial', false);
if (data) {
for (let perm in data) {

View File

@ -1,5 +1,4 @@
import { InitialReducer } from '/reducers/initial';
import { GroupUpdateReducer } from '/reducers/group-update';
import { ContactUpdateReducer } from '/reducers/contact-update';
import { ChatUpdateReducer } from '/reducers/chat-update';
import { InviteUpdateReducer } from '/reducers/invite-update';
@ -13,7 +12,6 @@ class Store {
this.state = {
inbox: {},
chatSynced: {},
groups: {},
contacts: {},
permissions: {},
invites: {},
@ -28,7 +26,6 @@ class Store {
};
this.initialReducer = new InitialReducer();
this.groupUpdateReducer = new GroupUpdateReducer();
this.permissionUpdateReducer = new PermissionUpdateReducer();
this.contactUpdateReducer = new ContactUpdateReducer();
this.chatUpdateReducer = new ChatUpdateReducer();
@ -47,7 +44,6 @@ class Store {
console.log(json);
this.initialReducer.reduce(json, this.state);
this.groupUpdateReducer.reduce(json, this.state);
this.permissionUpdateReducer.reduce(json, this.state);
this.contactUpdateReducer.reduce(json, this.state);
this.chatUpdateReducer.reduce(json, this.state);

View File

@ -5,50 +5,46 @@ import urbitOb from 'urbit-ob';
export class Subscription {
constructor() {
this.firstRoundSubscriptionComplete = false;
}
start() {
if (api.authTokens) {
this.initializeChat();
this.firstRoundSubscription();
} else {
console.error("~~~ ERROR: Must set api.authTokens before operation ~~~");
}
}
initializeChat() {
api.bind('/primary', 'PUT', api.authTokens.ship, 'chat-view',
subscribe(path, app) {
api.bind(path, 'PUT', api.authTokens.ship, app,
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/synced', 'PUT', api.authTokens.ship, 'chat-hook',
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),
this.handleQuitAndResubscribe.bind(this));
api.bind('/all', 'PUT', api.authTokens.ship, 'permission-store',
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/primary', 'PUT', api.authTokens.ship, 'contact-view',
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/app-name/chat', 'PUT', api.authTokens.ship, 'metadata-store',
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
api.bind('/app-name/contacts', 'PUT', api.authTokens.ship, 'metadata-store',
this.handleEvent.bind(this),
this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this));
() => {
this.subscribe(path, app);
});
}
firstRoundSubscription() {
this.subscribe('/primary', 'chat-view');
}
secondRoundSubscriptions() {
this.subscribe('/synced', 'chat-hook');
this.subscribe('/primary', 'invite-view');
this.subscribe('/all', 'permission-store');
this.subscribe('/primary', 'contact-view');
this.subscribe('/app-name/chat', 'metadata-store');
this.subscribe('/app-name/contacts', 'metadata-store');
}
handleEvent(diff) {
if (!this.firstRoundSubscriptionComplete) {
this.firstRoundSubscriptionComplete = true;
this.secondRoundSubscriptions();
}
store.handleEvent(diff);
}
@ -56,14 +52,6 @@ export class Subscription {
console.error(err);
}
handleQuitSilently(quit) {
// no-op
}
handleQuitAndResubscribe(quit) {
// TODO: resubscribe
}
fetchMessages(start, end, path) {
console.log(start, end, path);
fetch(`/~chat/paginate/${start}/${end}${path}`)