chat-js: improve subscription speed by doing two rounds of subscriptions and no longer subscribing to groups

This commit is contained in:
Logan Allen 2020-03-26 17:41:11 -04:00
parent 0d3e409f7c
commit 221238c0fa
12 changed files with 38 additions and 160 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/" : ""; const isinPopout = props.popout ? "popout/" : "";
@ -301,7 +301,6 @@ export class ChatScreen extends Component {
station={props.station} station={props.station}
owner={deSig(props.match.params.ship)} owner={deSig(props.match.params.ship)}
ownerContact={ownerContact} ownerContact={ownerContact}
permissions={props.permissions}
envelopes={props.envelopes} envelopes={props.envelopes}
contacts={props.contacts} contacts={props.contacts}
placeholder="Message..." placeholder="Message..."

View File

@ -422,36 +422,7 @@ export class ChatInput extends Component {
}); });
} }
readOnlyRender() { render() {
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() {
const { props, state } = this; const { props, state } = this;
let color = !!props.ownerContact let color = !!props.ownerContact
@ -505,29 +476,4 @@ export class ChatInput extends Component {
</div> </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

@ -30,7 +30,7 @@ export class InviteSearch extends Component {
} }
peerUpdate() { peerUpdate() {
let groups = Array.from(Object.keys(this.props.groups)); let groups = Array.from(Object.keys(this.props.permissions));
groups = groups.filter(e => !e.startsWith("/~/")) groups = groups.filter(e => !e.startsWith("/~/"))
.map(e => { .map(e => {
let eachGroup = new Set(); let eachGroup = new Set();
@ -49,15 +49,17 @@ export class InviteSearch extends Component {
let peers = [], let peers = [],
peerSet = new Set(), peerSet = new Set(),
contacts = new Map; contacts = new Map;
Object.keys(this.props.groups).map(group => {
if (this.props.groups[group].size > 0) { Object.keys(this.props.permissions).map(group => {
let groupEntries = this.props.groups[group].values(); if (this.props.permissions[group].who.size > 0) {
let groupEntries = this.props.permissions[group].who.values();
for (let member of groupEntries) { for (let member of groupEntries) {
peerSet.add(member); peerSet.add(member);
} }
} }
if (this.props.contacts[group]) { if (this.props.contacts[group]) {
let groupEntries = this.props.groups[group].values(); let groupEntries = this.props.permissions[group].who.values();
for (let member of groupEntries) { for (let member of groupEntries) {
if (this.props.contacts[group][member]) { if (this.props.contacts[group][member]) {
if (contacts.has(member)) { if (contacts.has(member)) {

View File

@ -259,7 +259,7 @@ export class NewScreen extends Component {
Selected groups or ships will be able to post to chat Selected groups or ships will be able to post to chat
</p> </p>
<InviteSearch <InviteSearch
groups={props.groups} permissions={props.permissions}
contacts={props.contacts} contacts={props.contacts}
associations={props.associations} associations={props.associations}
groupResults={true} groupResults={true}

View File

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

View File

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

View File

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

View File

@ -5,19 +5,27 @@ import urbitOb from 'urbit-ob';
export class Subscription { export class Subscription {
constructor() {
this.firstRoundSubscriptionComplete = false;
}
start() { start() {
if (api.authTokens) { if (api.authTokens) {
this.initializeChat(); this.firstRoundSubscription();
} else { } else {
console.error("~~~ ERROR: Must set api.authTokens before operation ~~~"); console.error("~~~ ERROR: Must set api.authTokens before operation ~~~");
} }
} }
initializeChat() { firstRoundSubscription() {
api.bind('/primary', 'PUT', api.authTokens.ship, 'chat-view', api.bind('/primary', 'PUT', api.authTokens.ship, 'chat-view',
this.handleEvent.bind(this), this.handleEvent.bind(this),
this.handleError.bind(this), this.handleError.bind(this),
this.handleQuitAndResubscribe.bind(this)); this.handleQuitAndResubscribe.bind(this));
}
secondRoundSubscriptions() {
api.bind('/synced', 'PUT', api.authTokens.ship, 'chat-hook', api.bind('/synced', 'PUT', api.authTokens.ship, 'chat-hook',
this.handleEvent.bind(this), this.handleEvent.bind(this),
this.handleError.bind(this), this.handleError.bind(this),
@ -26,10 +34,6 @@ export class Subscription {
this.handleEvent.bind(this), this.handleEvent.bind(this),
this.handleError.bind(this), this.handleError.bind(this),
this.handleQuitAndResubscribe.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', api.bind('/all', 'PUT', api.authTokens.ship, 'permission-store',
this.handleEvent.bind(this), this.handleEvent.bind(this),
this.handleError.bind(this), this.handleError.bind(this),
@ -49,6 +53,10 @@ export class Subscription {
} }
handleEvent(diff) { handleEvent(diff) {
if (!this.firstRoundSubscriptionComplete) {
this.firstRoundSubscriptionComplete = true;
this.secondRoundSubscriptions();
}
store.handleEvent(diff); store.handleEvent(diff);
} }