mirror of
https://github.com/ilyakooo0/urbit.git
synced 2025-01-02 03:52:13 +03:00
wip: store, subscription, api refactor to clear properly
This commit is contained in:
parent
8fc7d8cc69
commit
2494ed30aa
@ -50,7 +50,8 @@ export default class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const Channel = window.channel;
|
||||
const channel = window.channel;
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={light}>
|
||||
<Root>
|
||||
@ -59,19 +60,19 @@ export default class App extends React.Component {
|
||||
<div>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/~chat" render={
|
||||
p => <ChatApp ship={this.ship} channel={new Channel()} {...p} />
|
||||
p => <ChatApp ship={this.ship} channel={channel} {...p} />
|
||||
}
|
||||
/>
|
||||
<Route path="/~dojo" render={
|
||||
p => <DojoApp ship={this.ship} channel={new Channel()} {...p} />
|
||||
p => <DojoApp ship={this.ship} channel={channel} {...p} />
|
||||
}
|
||||
/>
|
||||
<Route path="/~groups" render={
|
||||
p => <GroupsApp ship={this.ship} channel={new Channel()} {...p} />
|
||||
p => <GroupsApp ship={this.ship} channel={channel} {...p} />
|
||||
}
|
||||
/>
|
||||
<Route path="/~link" render={
|
||||
p => <LinksApp ship={this.ship} channel={new Channel()} {...p} />
|
||||
p => <LinksApp ship={this.ship} channel={channel} {...p} />
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
|
||||
import api from './api';
|
||||
import store from './store';
|
||||
import subscription from './subscription';
|
||||
import Api from './api';
|
||||
import Store from './store';
|
||||
import Subscription from './subscription';
|
||||
|
||||
import './css/custom.css';
|
||||
|
||||
@ -19,9 +19,17 @@ import { NewDmScreen } from './components/new-dm';
|
||||
export default class ChatApp extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.store = new Store();
|
||||
this.store.setStateHandler(this.setState.bind(this));
|
||||
|
||||
this.state = store.state;
|
||||
this.totalUnreads = 0;
|
||||
store.setStateHandler(this.setState.bind(this));
|
||||
this.resetControllers();
|
||||
}
|
||||
|
||||
resetControllers() {
|
||||
this.api = null;
|
||||
this.subscription = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -29,20 +37,18 @@ export default class ChatApp extends React.Component {
|
||||
// preload spinner asset
|
||||
new Image().src = '/~chat/img/Spinner.png';
|
||||
|
||||
api.setAuthTokens(
|
||||
{ ship: this.props.ship },
|
||||
this.props.channel
|
||||
);
|
||||
this.store.clear();
|
||||
let channel = new this.props.channel();
|
||||
this.api = new Api(this.props.ship, channel);
|
||||
|
||||
subscription.start(this.props.channel);
|
||||
this.subscription = new Subscription(this.store, this.api, channel);
|
||||
this.subscription.start();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.channel.delete();
|
||||
store.firstRoundSubscriptionComplete = false;
|
||||
store.handleEvent({
|
||||
data: { clear: true }
|
||||
});
|
||||
this.subscription.delete();
|
||||
this.store.clear();
|
||||
this.resetControllers();
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -87,7 +93,7 @@ export default class ChatApp extends React.Component {
|
||||
contacts={contacts}
|
||||
invites={invites['/chat'] || {}}
|
||||
unreads={unreads}
|
||||
api={api}
|
||||
api={this.api}
|
||||
station={station}
|
||||
{...props}
|
||||
/>
|
||||
@ -133,7 +139,7 @@ export default class ChatApp extends React.Component {
|
||||
sidebarShown={state.sidebarShown}
|
||||
>
|
||||
<NewDmScreen
|
||||
api={api}
|
||||
api={this.api}
|
||||
inbox={state.inbox || {}}
|
||||
permissions={state.permissions || {}}
|
||||
contacts={state.contacts || {}}
|
||||
@ -159,7 +165,7 @@ export default class ChatApp extends React.Component {
|
||||
sidebarShown={state.sidebarShown}
|
||||
>
|
||||
<NewScreen
|
||||
api={api}
|
||||
api={this.api}
|
||||
inbox={state.inbox || {}}
|
||||
permissions={state.permissions || {}}
|
||||
contacts={state.contacts || {}}
|
||||
@ -191,7 +197,7 @@ export default class ChatApp extends React.Component {
|
||||
sidebarShown={state.sidebarShown}
|
||||
>
|
||||
<JoinScreen
|
||||
api={api}
|
||||
api={this.api}
|
||||
inbox={state.inbox}
|
||||
autoJoin={station}
|
||||
chatSynced={state.chatSynced || {}}
|
||||
@ -253,8 +259,8 @@ export default class ChatApp extends React.Component {
|
||||
chatSynced={state.chatSynced}
|
||||
station={station}
|
||||
association={association}
|
||||
api={api}
|
||||
subscription={subscription}
|
||||
api={this.api}
|
||||
subscription={this.subscription}
|
||||
read={mailbox.config.read}
|
||||
length={mailbox.config.length}
|
||||
envelopes={mailbox.envelopes}
|
||||
|
@ -2,9 +2,10 @@ import _ from 'lodash';
|
||||
import { uuid } from '../../lib/util';
|
||||
import store from './store';
|
||||
|
||||
class UrbitApi {
|
||||
setAuthTokens(authTokens, channel) {
|
||||
this.authTokens = authTokens;
|
||||
export default class Api {
|
||||
|
||||
constructor(ship, channel) {
|
||||
this.ship = ship;
|
||||
this.channel = channel;
|
||||
this.bindPaths = [];
|
||||
|
||||
@ -33,9 +34,10 @@ class UrbitApi {
|
||||
accept: this.inviteAccept.bind(this),
|
||||
decline: this.inviteDecline.bind(this)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bind(path, method, ship = this.authTokens.ship, app, success, fail, quit) {
|
||||
bind(path, method, ship = this.ship, app, success, fail, quit) {
|
||||
this.bindPaths = _.uniq([...this.bindPaths, path]);
|
||||
|
||||
window.subscriptionId = this.channel.subscribe(ship, app, path,
|
||||
@ -256,5 +258,3 @@ class UrbitApi {
|
||||
}
|
||||
}
|
||||
|
||||
const api = new UrbitApi();
|
||||
export default api;
|
||||
|
@ -7,7 +7,7 @@ import MetadataReducer from '../../reducers/metadata-update';
|
||||
import LocalReducer from '../../reducers/local';
|
||||
import S3Reducer from '../../reducers/s3';
|
||||
|
||||
class Store {
|
||||
export default class Store {
|
||||
constructor() {
|
||||
this.state = this.initialState();
|
||||
|
||||
@ -45,6 +45,12 @@ class Store {
|
||||
this.setState = setState;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.handleEvent({
|
||||
data: { clear: true }
|
||||
});
|
||||
}
|
||||
|
||||
handleEvent(data) {
|
||||
let json = data.data;
|
||||
|
||||
@ -66,5 +72,3 @@ class Store {
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Store();
|
||||
export default store;
|
||||
|
@ -1,34 +1,40 @@
|
||||
import api from './api';
|
||||
import store from './store';
|
||||
export default class Subscription {
|
||||
constructor(store, api, channel) {
|
||||
this.store = store;
|
||||
this.api = api;
|
||||
this.channel = channel;
|
||||
|
||||
export class Subscription {
|
||||
constructor() {
|
||||
this.firstRoundSubscriptionComplete = false;
|
||||
this.channel.setOnChannelError(this.onChannelError.bind(this));
|
||||
this.firstRoundComplete = false;
|
||||
}
|
||||
|
||||
start(channel) {
|
||||
if (api.authTokens) {
|
||||
this.firstRoundSubscription();
|
||||
channel.setOnChannelError(this.onChannelError.bind(this));
|
||||
start() {
|
||||
if (api.ship) {
|
||||
this.firstRound();
|
||||
} else {
|
||||
console.error('~~~ ERROR: Must set api.authTokens before operation ~~~');
|
||||
console.error('~~~ ERROR: Must set api.ship before operation ~~~');
|
||||
}
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.channel.delete();
|
||||
}
|
||||
|
||||
onChannelError(err) {
|
||||
console.error('event source error: ', err);
|
||||
console.log('initiating new channel');
|
||||
this.firstRoundSubscriptionComplete = false;
|
||||
this.firstRoundComplete = false;
|
||||
setTimeout(2000, () => {
|
||||
store.handleEvent({
|
||||
data: { clear : true }
|
||||
});
|
||||
|
||||
this.start();
|
||||
});
|
||||
}
|
||||
|
||||
subscribe(path, app) {
|
||||
api.bind(path, 'PUT', api.authTokens.ship, app,
|
||||
api.bind(path, 'PUT', api.ship, app,
|
||||
this.handleEvent.bind(this),
|
||||
(err) => {
|
||||
console.log(err);
|
||||
@ -39,7 +45,7 @@ export class Subscription {
|
||||
});
|
||||
}
|
||||
|
||||
firstRoundSubscription() {
|
||||
firstRound() {
|
||||
this.subscribe('/primary', 'chat-view');
|
||||
}
|
||||
|
||||
@ -53,16 +59,16 @@ export class Subscription {
|
||||
}
|
||||
|
||||
handleEvent(diff) {
|
||||
if (!this.firstRoundSubscriptionComplete) {
|
||||
this.firstRoundSubscriptionComplete = true;
|
||||
this.secondRoundSubscriptions();
|
||||
if (!this.firstRoundComplete) {
|
||||
this.firstRoundComplete = true;
|
||||
this.secondRound();
|
||||
}
|
||||
store.handleEvent(diff);
|
||||
}
|
||||
|
||||
fetchMessages(start, end, path) {
|
||||
console.log(start, end, path);
|
||||
fetch(`/~chat/paginate/${start}/${end}${path}`)
|
||||
fetch(`/chat-view/paginate/${start}/${end}${path}`)
|
||||
.then(response => response.json())
|
||||
.then((json) => {
|
||||
store.handleEvent({
|
||||
@ -72,5 +78,3 @@ export class Subscription {
|
||||
}
|
||||
}
|
||||
|
||||
const subscription = new Subscription();
|
||||
export default subscription;
|
||||
|
@ -6,37 +6,43 @@ import { Popout } from './components/lib/icons/popout';
|
||||
import { History } from './components/history';
|
||||
import { Input } from './components/input';
|
||||
|
||||
import store from './store';
|
||||
import api from './api';
|
||||
import subscription from './subscription';
|
||||
import Api from './api';
|
||||
import Store from './store';
|
||||
import Subscription from './subscription';
|
||||
|
||||
import './css/custom.css';
|
||||
|
||||
export default class DojoApp extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.store = new Store();
|
||||
this.store.setStateHandler(this.setState.bind(this));
|
||||
|
||||
this.state = store.state;
|
||||
store.setStateHandler(this.setState.bind(this));
|
||||
this.resetControllers();
|
||||
}
|
||||
|
||||
resetControllers() {
|
||||
this.api = null;
|
||||
this.subscription = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.title = 'OS1 - Dojo';
|
||||
api.setAuthTokens(
|
||||
{
|
||||
ship: this.props.ship,
|
||||
dojoId: 'soto-' + Math.random().toString(36).substring(2)
|
||||
},
|
||||
this.props.channel
|
||||
);
|
||||
|
||||
let channel = new this.props.channel();
|
||||
this.api = new Api(this.props.ship, channel);
|
||||
|
||||
this.subscription = new Subscription(this.store, this.api, channel);
|
||||
this.subscription.start();
|
||||
|
||||
subscription.start(this.props.channel);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.channel.delete();
|
||||
store.handleEvent({
|
||||
data: { clear: true }
|
||||
});
|
||||
this.subscription.delete();
|
||||
this.store.clear();
|
||||
this.resetControllers();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -1,13 +1,15 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
class UrbitApi {
|
||||
setAuthTokens(authTokens, channel) {
|
||||
this.authTokens = authTokens;
|
||||
export default class Api {
|
||||
|
||||
constructor(ship, channel) {
|
||||
this.ship = ship;
|
||||
this.channel = channel;
|
||||
this.bindPaths = [];
|
||||
this.dojoId = 'soto-' + Math.random().toString(36).substring(2);
|
||||
}
|
||||
|
||||
bind(path, method, ship = this.authTokens.ship, appl = 'dojo', success, fail) {
|
||||
bind(path, method, ship = this.ship, appl = 'dojo', success, fail) {
|
||||
this.bindPaths = _.uniq([...this.bindPaths, path]);
|
||||
|
||||
window.subscriptionId = this.channel.subscribe(ship, appl, path,
|
||||
@ -29,9 +31,7 @@ class UrbitApi {
|
||||
}
|
||||
|
||||
soto(data) {
|
||||
return this.action('dojo', 'sole-action',
|
||||
{ id: this.authTokens.dojoId, dat: data }
|
||||
);
|
||||
return this.action('dojo', 'sole-action', { id: this.dojoId, dat: data });
|
||||
}
|
||||
|
||||
action(appl, mark, data) {
|
||||
@ -47,5 +47,3 @@ class UrbitApi {
|
||||
}
|
||||
}
|
||||
|
||||
const api = new UrbitApi();
|
||||
export default api;
|
||||
|
@ -1,13 +1,12 @@
|
||||
import Share from './components/lib/sole';
|
||||
import api from './api';
|
||||
|
||||
export const buffer = new Share();
|
||||
|
||||
export class Store {
|
||||
export default class Store {
|
||||
constructor() {
|
||||
this.state = this.initialState();
|
||||
this.sync = this.sync.bind(this);
|
||||
this.print = this.print.bind(this);
|
||||
this.buffer = new Share();
|
||||
}
|
||||
|
||||
initialState() {
|
||||
@ -51,7 +50,7 @@ export class Store {
|
||||
case 'hop':
|
||||
return this.setState({ cursor: dojoReply.hop });
|
||||
case 'det':
|
||||
buffer.receive(dojoReply.det);
|
||||
this.buffer.receive(dojoReply.det);
|
||||
return this.sync(dojoReply.det.ted);
|
||||
case 'act':
|
||||
switch (dojoReply.act) {
|
||||
@ -67,7 +66,7 @@ export class Store {
|
||||
}
|
||||
|
||||
doEdit(ted) {
|
||||
const detSend = buffer.transmit(ted);
|
||||
const detSend = this.buffer.transmit(ted);
|
||||
this.sync(ted);
|
||||
return api.soto({ det: detSend });
|
||||
}
|
||||
@ -80,8 +79,8 @@ export class Store {
|
||||
|
||||
sync(ted) {
|
||||
return this.setState({
|
||||
input: buffer.buf,
|
||||
cursor: buffer.transpose(ted, this.state.cursor)
|
||||
input: this.buffer.buf,
|
||||
cursor: this.buffer.transpose(ted, this.state.cursor)
|
||||
});
|
||||
}
|
||||
|
||||
@ -90,5 +89,3 @@ export class Store {
|
||||
}
|
||||
}
|
||||
|
||||
const store = new Store();
|
||||
export default store;
|
||||
|
@ -1,34 +1,59 @@
|
||||
import api from './api';
|
||||
import store from './store';
|
||||
|
||||
export class Subscription {
|
||||
export default class Subscription {
|
||||
constructor(store, api, channel) {
|
||||
this.store = store;
|
||||
this.api = api;
|
||||
this.channel = channel;
|
||||
|
||||
this.channel.setOnChannelError(this.onChannelError.bind(this));
|
||||
this.firstRoundComplete = false;
|
||||
}
|
||||
|
||||
start() {
|
||||
if (api.authTokens) {
|
||||
this.initializesoto();
|
||||
if (api.ship) {
|
||||
this.firstRound();
|
||||
} else {
|
||||
console.error('~~~ ERROR: Must set api.authTokens before operation ~~~');
|
||||
console.error('~~~ ERROR: Must set api.ship before operation ~~~');
|
||||
}
|
||||
}
|
||||
|
||||
initializesoto() {
|
||||
api.bind('/sole/' + api.authTokens.dojoId,
|
||||
'PUT', api.authTokens.ship, 'dojo',
|
||||
delete() {
|
||||
this.channel.delete();
|
||||
}
|
||||
|
||||
onChannelError(err) {
|
||||
console.error('event source error: ', err);
|
||||
console.log('initiating new channel');
|
||||
this.firstRoundComplete = false;
|
||||
setTimeout(2000, () => {
|
||||
store.handleEvent({
|
||||
data: { clear : true }
|
||||
});
|
||||
|
||||
this.start();
|
||||
});
|
||||
}
|
||||
|
||||
subscribe(path, app) {
|
||||
api.bind(path, 'PUT', api.ship, app,
|
||||
this.handleEvent.bind(this),
|
||||
this.handleError.bind(this));
|
||||
(err) => {
|
||||
console.log(err);
|
||||
this.subscribe(path, app);
|
||||
},
|
||||
() => {
|
||||
this.subscribe(path, app);
|
||||
});
|
||||
}
|
||||
|
||||
firstRound() {
|
||||
this.subsribe('/sole/' + api.dojoId, 'dojo');
|
||||
}
|
||||
|
||||
handleEvent(diff) {
|
||||
store.handleEvent(diff);
|
||||
}
|
||||
|
||||
handleError(err) {
|
||||
console.error(err);
|
||||
api.bind('/sole/' + api.authTokens.dojoId,
|
||||
'PUT', api.authTokens.ship, 'dojo',
|
||||
this.handleEvent.bind(this),
|
||||
this.handleError.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
const subscription = new Subscription();
|
||||
export default subscription;
|
Loading…
Reference in New Issue
Block a user