Merge branch 'release/next-userspace' into m/next-gen-term

This commit is contained in:
fang 2021-06-25 19:51:10 +02:00
commit 4ccfae930c
No known key found for this signature in database
GPG Key ID: EB035760C1BBA972
8 changed files with 84 additions and 55 deletions

View File

@ -9,12 +9,16 @@ import useLaunchState from '../state/launch';
import useSettingsState from '../state/settings';
import useLocalState from '../state/local';
export const bootstrapApi = async () => {
await airlock.poke({ app: 'hood', mark: 'helm-hi', json: 'opening airlock' });
export async function bootstrapApi() {
airlock.onError = (e) => {
(async () => {
useLocalState.setState({ subscription: 'disconnected' });
const { reconnect } = useLocalState.getState();
try {
useLocalState.setState({ subscription: 'reconnecting' });
await reconnect();
} catch (e) {
useLocalState.setState({ subscription: 'disconnected' });
}
})();
};
@ -26,8 +30,7 @@ export const bootstrapApi = async () => {
useLocalState.setState({ subscription: 'connected' });
};
await airlock.eventSource();
[
const promises = [
useHarkState,
useMetadataState,
useGroupState,
@ -36,8 +39,7 @@ export const bootstrapApi = async () => {
useLaunchState,
useInviteState,
useGraphState
].forEach((state) => {
state.getState().initialize(airlock);
});
};
].map(state => state.getState().initialize(airlock));
await Promise.all(promises);
}

View File

@ -9,6 +9,9 @@ import produce from 'immer';
import _ from 'lodash';
import { BaseState, reduceState } from '../state/base';
import useGraphState, { GraphState as State } from '../state/graph';
/* eslint-disable camelcase */
import { unstable_batchedUpdates } from 'react-dom';
type GraphState = State & BaseState<State>;
@ -456,27 +459,29 @@ export const reduceDm = [
export const GraphReducer = (json) => {
const data = _.get(json, 'graph-update', false);
if (data) {
reduceState<GraphState, any>(useGraphState, data, [
keys,
addGraph,
removeGraph,
addNodes,
removePosts
]);
}
const loose = _.get(json, 'graph-update-loose', false);
if(loose) {
reduceState<GraphState, any>(useGraphState, loose, [addNodesLoose]);
}
unstable_batchedUpdates(() => {
if (data) {
reduceState<GraphState, any>(useGraphState, data, [
keys,
addGraph,
removeGraph,
addNodes,
removePosts
]);
}
const loose = _.get(json, 'graph-update-loose', false);
if(loose) {
reduceState<GraphState, any>(useGraphState, loose, [addNodesLoose]);
}
const flat = _.get(json, 'graph-update-flat', false);
if (flat) {
reduceState<GraphState, any>(useGraphState, flat, [addNodesFlat]);
}
const flat = _.get(json, 'graph-update-flat', false);
if (flat) {
reduceState<GraphState, any>(useGraphState, flat, [addNodesFlat]);
}
const thread = _.get(json, 'graph-update-thread', false);
if (thread) {
reduceState<GraphState, any>(useGraphState, thread, [addNodesThread]);
}
const thread = _.get(json, 'graph-update-thread', false);
if (thread) {
reduceState<GraphState, any>(useGraphState, thread, [addNodesThread]);
}
});
};

View File

@ -93,7 +93,7 @@ export interface BaseState<StateType extends {}> {
addPatch: (id: string, ...patch: Patch[]) => void;
removePatch: (id: string) => void;
optSet: (fn: (state: StateType & BaseState<StateType>) => void) => string;
initialize: (api: Urbit) => void;
initialize: (api: Urbit) => Promise<void>;
}
export function createSubscription(app: string, path: string, e: (data: any) => void): SubscriptionRequestInterface {
@ -114,8 +114,8 @@ export const createState = <T extends {}>(
blacklist: (keyof BaseState<T> | keyof T)[] = [],
subscriptions: ((set: SetState<T & BaseState<T>>, get: GetState<T & BaseState<T>>) => SubscriptionRequestInterface)[] = []
): UseStore<T & BaseState<T>> => create<T & BaseState<T>>(persist<T & BaseState<T>>((set, get) => ({
initialize: (api: Urbit) => {
subscriptions.forEach(sub => api.subscribe(sub(set, get)));
initialize: async (api: Urbit) => {
await Promise.all(subscriptions.map(sub => api.subscribe(sub(set, get))));
},
// @ts-ignore investigate zustand types
set: fn => stateSetter(fn, set, get),

View File

@ -6,6 +6,7 @@ import { persist } from 'zustand/middleware';
import { BackgroundConfig, LeapCategories, RemoteContentPolicy, TutorialProgress, tutorialProgress } from '~/types/local-update';
import airlock from '~/logic/api';
import { bootstrapApi } from '../api/bootstrap';
import { wait } from '~/logic/lib/util';
export type SubscriptionStatus = 'connected' | 'disconnected' | 'reconnecting';
@ -31,7 +32,9 @@ export interface LocalState {
toggleOmnibox: () => void;
set: (fn: (state: LocalState) => void) => void;
subscription: SubscriptionStatus;
restartSubscription: () => Promise<void>;
reconnect: () => Promise<void>;
bootstrap: () => Promise<void>;
errorCount: number;
}
type LocalStateZus = LocalState & State;
@ -89,31 +92,39 @@ const useLocalState = create<LocalStateZus>(persist((set, get) => ({
}
})),
subscription: 'connected',
restartSubscription: async () => {
try {
set({ subscription: 'reconnecting' });
await airlock.eventSource();
set({ subscription: 'connected' });
} catch (e) {
errorCount: 0,
// XX this logic should be handled by eventsource lib, but channel$a
// resume doesn't work properly
reconnect: async () => {
const { errorCount } = get();
if(errorCount > 5) {
set({ subscription: 'disconnected' });
return;
}
try {
airlock.reset();
await bootstrapApi();
} catch (e) {
await wait(Math.pow(2, errorCount) * 750);
set({ errorCount: errorCount + 1 });
const { reconnect } = get();
await reconnect();
}
},
bootstrap: async () => {
try {
set({ subscription: 'reconnecting' });
airlock.reset();
await bootstrapApi();
set({ subscription: 'connected' });
} catch (e) {
set({ subscription: 'disconnected' });
}
set({ subscription: 'reconnecting' });
airlock.reset();
await bootstrapApi();
set({ subscription: 'connected' });
},
// @ts-ignore investigate zustand types
set: fn => set(produce(fn))
}), {
blacklist: [
'suspendedFocus', 'toggleOmnibox', 'omniboxShown', 'tutorialProgress',
'prevTutStep', 'nextTutStep', 'tutorialRef', 'setTutorialRef'
'prevTutStep', 'nextTutStep', 'tutorialRef', 'setTutorialRef', 'subscription'
],
name: 'localReducer'
}));

View File

@ -1,6 +1,6 @@
import { Col, Row, Text } from '@tlon/indigo-react';
import { Association, Graph, GraphNode } from '@urbit/api';
import React, { useCallback, useState, useMemo } from 'react';
import { Association, Graph, GraphNode, markEachAsRead } from '@urbit/api';
import React, { useCallback, useState, useMemo, useEffect } from 'react';
import _ from 'lodash';
import { useResize } from '~/logic/lib/useResize';
import { LinkBlockItem } from './LinkBlockItem';
@ -8,6 +8,8 @@ import { LinkBlockInput } from './LinkBlockInput';
import useLocalState from '~/logic/state/local';
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import bigInt from 'big-integer';
import airlock from '~/logic/api';
import useHarkState from '~/logic/state/hark';
import { BlockScroller } from '~/views/components/BlockScroller';
export interface LinkBlocksProps {
@ -40,6 +42,14 @@ export function LinkBlocks(props: LinkBlocksProps) {
)
);
useEffect(() => {
const { unreads } = useHarkState
.getState().unreads.graph?.[association.resource]?.['/'];
Array.from((unreads as Set<string>)).forEach((u) => {
airlock.poke(markEachAsRead(association.resource, '/', u));
});
}, [association.resource]);
const orm = useMemo(() => {
const nodes = [null, ...Array.from(props.graph)];

View File

@ -276,7 +276,6 @@ export const RemoteContentOembed = React.forwardRef<
const detail = (
<Col
mb={embed?.html && !thumbnail ? 0 : 2}
width="100%"
flexShrink={0}
height="100%"

View File

@ -24,7 +24,8 @@ export function RemoteContentWrapper(props: RemoteContentWrapperProps) {
} = props;
const [unfold, setUnfold] = useState(false);
const toggleUnfold = useCallback(() => {
const toggleUnfold = useCallback((e: React.MouseEvent) => {
e.stopPropagation();
setUnfold(s => !s);
}, []);

View File

@ -240,7 +240,8 @@ export class Urbit {
}
},
onerror: (error) => {
if(this.errorCount++ < 5) {
// Channel resume currently broken in eyre
if(false && this.errorCount++ < 5) {
console.log(this.errorCount);
this.onRetry && this.onRetry();
return Math.pow(2, this.errorCount - 1) * 750;