mirror of
https://github.com/urbit/shrub.git
synced 2024-12-29 23:23:52 +03:00
Merge branch 'release/next-userspace' into m/next-gen-term
This commit is contained in:
commit
4ccfae930c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -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),
|
||||
|
@ -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'
|
||||
}));
|
||||
|
@ -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)];
|
||||
|
||||
|
@ -276,7 +276,6 @@ export const RemoteContentOembed = React.forwardRef<
|
||||
|
||||
const detail = (
|
||||
<Col
|
||||
mb={embed?.html && !thumbnail ? 0 : 2}
|
||||
width="100%"
|
||||
flexShrink={0}
|
||||
height="100%"
|
||||
|
@ -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);
|
||||
}, []);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user