mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-09-21 07:28:30 +03:00
Merge branch 'release/next-userspace' into lf/groups-refactor
This commit is contained in:
commit
b8c8170eb2
@ -9,6 +9,9 @@ class Channel {
|
||||
this.onChannelError = (err) => {
|
||||
console.error('event source error: ', err);
|
||||
};
|
||||
this.onChannelOpen = (e) => {
|
||||
console.log('open', e);
|
||||
};
|
||||
}
|
||||
|
||||
init() {
|
||||
@ -58,6 +61,10 @@ class Channel {
|
||||
this.onChannelError = onError;
|
||||
}
|
||||
|
||||
setOnChannelOpen(onOpen = (e) => {}) {
|
||||
this.onChannelOpen = onOpen;
|
||||
}
|
||||
|
||||
deleteOnUnload() {
|
||||
window.addEventListener("unload", (event) => {
|
||||
this.delete();
|
||||
@ -216,6 +223,8 @@ class Channel {
|
||||
}
|
||||
}
|
||||
|
||||
this.eventSource.onopen = this.onChannelOpen;
|
||||
|
||||
this.eventSource.onerror = e => {
|
||||
this.delete();
|
||||
this.init();
|
||||
|
@ -95,6 +95,8 @@ class App extends React.Component {
|
||||
associations={associations}
|
||||
invites={this.state.invites}
|
||||
api={this.api}
|
||||
connection={this.state.connection}
|
||||
subscription={this.subscription}
|
||||
/>
|
||||
<Content>
|
||||
<Switch>
|
||||
|
@ -33,6 +33,9 @@ const StatusBar = (props) => {
|
||||
const invites = (props.invites && props.invites['/contacts'])
|
||||
? props.invites['/contacts']
|
||||
: {};
|
||||
const connection = props.connection || 'connected';
|
||||
|
||||
const reconnect = props.subscription.restart.bind(props.subscription);
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -65,6 +68,15 @@ const StatusBar = (props) => {
|
||||
</Link>
|
||||
}
|
||||
<p className="dib f9 v-mid inter ml2 white-d">{locationName}</p>
|
||||
{ connection === 'disconnected' &&
|
||||
(<span
|
||||
onClick={reconnect}
|
||||
className="ml4 ph2 dib f9 v-mid red2 inter ba b-red2 br1 pointer"
|
||||
>Reconnect ↻</span> )
|
||||
}
|
||||
{ connection === 'reconnecting' &&
|
||||
(<span className="ml4 ph2 dib f9 v-mid yellow2 inter ba b-yellow2 br1">Reconnecting</span> )
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
14
pkg/interface/src/reducers/connection.ts
Normal file
14
pkg/interface/src/reducers/connection.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import _ from 'lodash';
|
||||
import { StoreState } from '../store/type';
|
||||
import { Cage } from '../types/cage';
|
||||
|
||||
type LocalState = Pick<StoreState, 'connection'>;
|
||||
|
||||
export default class ConnectionReducer<S extends LocalState> {
|
||||
reduce(json: Cage, state: S) {
|
||||
if('connection' in json && json.connection) {
|
||||
console.log(`Conn: ${json.connection}`);
|
||||
state.connection = json.connection;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import PublishUpdateReducer from '../reducers/publish-update';
|
||||
import PublishResponseReducer from '../reducers/publish-response';
|
||||
import LaunchReducer from '../reducers/launch-update';
|
||||
import LinkListenReducer from '../reducers/listen-update';
|
||||
import ConnectionReducer from '../reducers/connection';
|
||||
|
||||
|
||||
export default class GlobalStore extends BaseStore<StoreState> {
|
||||
@ -31,12 +32,14 @@ export default class GlobalStore extends BaseStore<StoreState> {
|
||||
publishUpdateReducer = new PublishUpdateReducer();
|
||||
publishResponseReducer = new PublishResponseReducer();
|
||||
launchReducer = new LaunchReducer();
|
||||
connReducer = new ConnectionReducer();
|
||||
|
||||
|
||||
initialState(): StoreState {
|
||||
return {
|
||||
pendingMessages: new Map(),
|
||||
chatInitialized: false,
|
||||
connection: 'connected',
|
||||
sidebarShown: true,
|
||||
baseHash: null,
|
||||
invites: {},
|
||||
@ -90,5 +93,6 @@ export default class GlobalStore extends BaseStore<StoreState> {
|
||||
this.publishResponseReducer.reduce(data, this.state);
|
||||
this.launchReducer.reduce(data, this.state);
|
||||
this.linkListenReducer.reduce(data, this.state);
|
||||
this.connReducer.reduce(data, this.state);
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,14 @@ import { S3State } from '../types/s3-update';
|
||||
import { Permissions } from '../types/permission-update';
|
||||
import { LaunchState, WeatherState } from '../types/launch-update';
|
||||
import { LinkComments, LinkCollections, LinkSeen } from '../types/link-update';
|
||||
import { ConnectionStatus } from '../types/connection';
|
||||
|
||||
export interface StoreState {
|
||||
// local state
|
||||
sidebarShown: boolean;
|
||||
selectedGroups: SelectedGroup[];
|
||||
dark: boolean;
|
||||
connection: ConnectionStatus;
|
||||
baseHash: string | null;
|
||||
// invite state
|
||||
invites: Invites;
|
||||
|
@ -3,20 +3,39 @@ import BaseApi from "../api/base";
|
||||
import { Path } from "../types/noun";
|
||||
|
||||
export default class BaseSubscription<S extends object> {
|
||||
private errorCount = 0;
|
||||
constructor(public store: BaseStore<S>, public api: BaseApi<S>, public channel: any) {
|
||||
this.channel.setOnChannelError(this.onChannelError.bind(this));
|
||||
this.channel.setOnChannelOpen(this.onChannelOpen.bind(this));
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.channel.delete();
|
||||
}
|
||||
|
||||
// Exists to allow subclasses to hook
|
||||
restart() {
|
||||
this.handleEvent({ data: { connection: 'reconnecting' }});
|
||||
this.start();
|
||||
}
|
||||
|
||||
onChannelOpen(e: any) {
|
||||
this.errorCount = 0;
|
||||
this.handleEvent({ data: { connection: 'connected' }});
|
||||
}
|
||||
|
||||
onChannelError(err) {
|
||||
console.error('event source error: ', err);
|
||||
this.errorCount++;
|
||||
if(this.errorCount >= 5) {
|
||||
console.error("bailing out, too many retries");
|
||||
this.handleEvent({ data: { connection: 'disconnected' }});
|
||||
return;
|
||||
}
|
||||
this.handleEvent({ data: { connection: 'reconnecting' }});
|
||||
setTimeout(() => {
|
||||
this.store.clear();
|
||||
this.start();
|
||||
}, 2000);
|
||||
this.restart();
|
||||
}, Math.pow(2,this.errorCount - 1) * 750);
|
||||
}
|
||||
|
||||
subscribe(path: Path, app: string) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import BaseSubscription from './base';
|
||||
import { StoreState } from '../store/type';
|
||||
import { Path } from '../types/noun';
|
||||
import _ from 'lodash';
|
||||
|
||||
|
||||
/**
|
||||
@ -51,6 +52,16 @@ export default class GlobalSubscription extends BaseSubscription<StoreState> {
|
||||
this.subscribe('/all', 'weather');
|
||||
}
|
||||
|
||||
restart() {
|
||||
super.restart();
|
||||
_.mapValues(this.openSubscriptions, (subs, app: AppName) => {
|
||||
if(subs.length > 0) {
|
||||
this.stopApp(app);
|
||||
this.startApp(app);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startApp(app: AppName) {
|
||||
if(this.openSubscriptions[app].length > 0) {
|
||||
console.log(`${app} already started`);
|
||||
|
@ -10,6 +10,7 @@ import { GroupUpdate } from "./group-update";
|
||||
import { PermissionUpdate } from "./permission-update";
|
||||
import { LaunchUpdate, WeatherState } from "./launch-update";
|
||||
import { LinkListenUpdate } from './link-listen-update';
|
||||
import { ConnectionStatus } from "./connection";
|
||||
|
||||
interface MarksToTypes {
|
||||
readonly json: any;
|
||||
@ -28,6 +29,7 @@ interface MarksToTypes {
|
||||
readonly 'local': LocalUpdate;
|
||||
readonly 'weather': WeatherState | {};
|
||||
readonly 'location': string;
|
||||
readonly 'connection': ConnectionStatus;
|
||||
}
|
||||
|
||||
export type Cage = Partial<MarksToTypes>;
|
||||
|
2
pkg/interface/src/types/connection.ts
Normal file
2
pkg/interface/src/types/connection.ts
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
export type ConnectionStatus = 'reconnecting' | 'disconnected' | 'connected';
|
Loading…
Reference in New Issue
Block a user