bootstrap: moving and reordering, adding scries

This undoes some of the code-splitting done previously as it didn't
affect performance enough, and was actively hurting it in some ways.
Instead this moves the subscription initiation higher and adds scries
for critical data. This also shuffles the calls in App's useEffect so
that they are more colocated with relevant concerns.
This commit is contained in:
Hunter Miller 2022-03-24 19:17:42 -05:00
parent edb4094301
commit e3b2e166d7
6 changed files with 184 additions and 192 deletions

View File

@ -1,7 +1,11 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { bootstrapApi } from './logic/api/bootstrap';
import './register-sw';
import './storage-wipe';
import App from './views/App';
// Start subscriptions as soon as possible before rendering anything
bootstrapApi();
ReactDOM.render(<App />, document.getElementById('root'));

View File

@ -9,6 +9,7 @@ import useLaunchState from '../state/launch';
import useSettingsState from '../state/settings';
import useLocalState from '../state/local';
import useStorageState from '../state/storage';
import gcpManager from '../lib/gcpManager';
export async function bootstrapApi() {
airlock.onError = (e) => {
@ -38,11 +39,11 @@ export async function bootstrapApi() {
} = useGraphState.getState();
clear();
getKeys();
getShallowChildren(`~${window.ship}`, 'dm-inbox');
useHarkState.getState().getUnreads();
getShallowChildren(`~${window.ship}`, 'dm-inbox');
await airlock.eventSource();
const promises = [
useGraphState,
[
useMetadataState,
useGroupState,
useContactState,
@ -50,8 +51,9 @@ export async function bootstrapApi() {
useInviteState,
useHarkState,
useStorageState,
useLaunchState
useLaunchState,
useGraphState
].map(state => state.getState().initialize(airlock));
await Promise.all(promises);
useSettingsState.getState().getAll();
gcpManager.start();
}

View File

@ -1,6 +1,3 @@
import Mousetrap from 'mousetrap';
import shallow from 'zustand/shallow';
import 'mousetrap-global-bind';
import * as React from 'react';
import Helmet from 'react-helmet';
import { Router, withRouter } from 'react-router-dom';
@ -9,9 +6,7 @@ import gcpManager from '~/logic/lib/gcpManager';
import { svgDataURL } from '~/logic/lib/util';
import history from '~/logic/lib/history';
import { favicon } from '~/logic/state/contact';
import useLocalState, { selectLocalState } from '~/logic/state/local';
import useSettingsState, { selectSettingsState, SettingsState } from '~/logic/state/settings';
import useGraphState, { GraphState } from '~/logic/state/graph';
import { SettingsState } from '~/logic/state/settings';
import { ShortcutContextProvider } from '~/logic/lib/shortcutContext';
import ErrorBoundary from '~/views/components/ErrorBoundary';
@ -22,7 +17,6 @@ import './css/fonts.css';
import './css/indigo-static.css';
import { Content } from './landscape/components/Content';
import './landscape/css/custom.css';
import { bootstrapApi } from '~/logic/api/bootstrap';
import { uxToHex } from '@urbit/api';
import { useThemeWatcher } from '~/logic/lib/useThemeWatcher';
@ -83,27 +77,11 @@ const Root = styled.div<RootProps>`
const StatusBarWithRouter = withRouter(StatusBar);
const selLocal = selectLocalState(['toggleOmnibox']);
const selSettings = selectSettingsState(['display', 'getAll']);
const selGraph = (s: GraphState) => s.getShallowChildren;
const App: React.FunctionComponent = () => {
const { getAll } = useSettingsState(selSettings, shallow);
const { toggleOmnibox } = useLocalState(selLocal);
const getShallowChildren = useGraphState(selGraph);
const { theme, display } = useThemeWatcher();
React.useEffect(() => {
bootstrapApi();
getShallowChildren(`~${window.ship}`, 'dm-inbox');
getAll();
gcpManager.start();
Mousetrap.bindGlobal(['command+/', 'ctrl+/'], (e) => {
e.preventDefault();
e.stopImmediatePropagation();
toggleOmnibox();
});
}, []);
return (

View File

@ -7,7 +7,9 @@ import {
Row,
Text
} from '@tlon/indigo-react';
import React from 'react';
import Mousetrap from 'mousetrap';
import 'mousetrap-global-bind';
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { Sigil } from '~/logic/lib/sigil';
import { uxToHex } from '~/logic/lib/util';
@ -46,6 +48,14 @@ const StatusBar = () => {
<Sigil ship={ship} size={16} color={color} icon />
);
useEffect(() => {
Mousetrap.bindGlobal(['command+/', 'ctrl+/'], (e) => {
e.preventDefault();
e.stopImmediatePropagation();
toggleOmnibox();
});
}, []);
return (
<Box
display='grid'

View File

@ -7,6 +7,11 @@ import { PermalinkRoutes } from '~/views/apps/permalinks/app';
import { useShortcut } from '~/logic/state/settings';
import { Loading } from '~/views/components/Loading';
import LaunchApp from '~/views/apps/launch/App';
import Landscape from '~/views/landscape';
import Settings from '~/views/apps/settings/settings';
import Profile from '~/views/apps/profile/profile';
import Notifications from '~/views/apps/notifications/notifications';
import ErrorComponent from '~/views/components/Error';
import { getNotificationRedirect } from '~/logic/lib/notificationRedirects';
import { JoinRoute } from './Join/Join';
@ -20,12 +25,6 @@ export const Container = styled(Box)`
height: calc(100% - 62px);
`;
const Landscape = React.lazy(() => import('~/views/landscape/index'));
const Settings = React.lazy(() => import('~/views/apps/settings/settings'));
const Profile = React.lazy(() => import('~/views/apps/profile/profile'));
const Notifications = React.lazy(() => import('~/views/apps/notifications/notifications'));
const ErrorComponent = React.lazy(() => import('~/views/components/Error'));
export const Content = () => {
const history = useHistory();
const location = useLocation();

View File

@ -21,18 +21,17 @@ import { PopoverRoutes } from './PopoverRoutes';
import { Skeleton } from './Skeleton';
import { EmptyGroupHome } from './Home/EmptyGroupHome';
import { Join } from './Join/Join';
import { Resource } from './Resource';
import { DmResource } from '~/views/apps/chat/DmResource';
import { UnjoinedResource } from '~/views/components/UnjoinedResource';
import { NewChannel } from './NewChannel';
import { GroupHome } from './Home/GroupHome';
interface GroupsPaneProps {
baseUrl: string;
workspace: Workspace;
}
const DmResource = React.lazy(() => import('~/views/apps/chat/DmResource').then(module => ({ default: module.DmResource })));
const Resource = React.lazy(() => import('./Resource').then(module => ({ default: module.Resource })));
const UnjoinedResource = React.lazy(() => import('~/views/components/UnjoinedResource').then(module => ({ default: module.UnjoinedResource })));
const GroupHome = React.lazy(() => import('./Home/GroupHome').then(module => ({ default: module.GroupHome })));
const NewChannel = React.lazy(() => import('./NewChannel').then(module => ({ default: module.NewChannel })));
export function GroupsPane(props: GroupsPaneProps) {
const { baseUrl, workspace } = props;
const associations = useMetadataState(state => state.associations);
@ -93,170 +92,170 @@ export function GroupsPane(props: GroupsPaneProps) {
);
return (
<Switch>
<Route
path={relativePath('/dm/:ship')}
render={({ match }) => {
const { ship } = match.params as Record<string, string>;
<Switch>
<Route
path={relativePath('/dm/:ship')}
render={({ match }) => {
const { ship } = match.params as Record<string, string>;
return (
<Skeleton
mobileHide
recentGroups={recentGroups}
selected={ship}
{...props}
baseUrl={match.path}
> <DmResource ship={ship} />
</Skeleton>
);
}}
/>
<Route
path={[relativePath('/resource/:app/(ship)?/:host/:name')]}
render={(routeProps) => {
const { app, host, name } = routeProps.match.params as Record<
string,
string
>;
const resource = `/ship/${host}/${name}`;
const association = associations.graph[resource];
const resourceUrl = `${baseUrl}/resource/${app}${resource}`;
if (!association) {
return <Loading />;
}
return (
<Skeleton
mobileHide
recentGroups={recentGroups}
selected={resource}
{...props}
baseUrl={resourceUrl}
>
<Resource
workspace={props.workspace}
association={association}
baseUrl={baseUrl}
/>
{popovers(routeProps, resourceUrl)}
</Skeleton>
);
}}
/>
<Route
path={relativePath('/join/:app/(ship)?/:host/:name')}
render={(routeProps) => {
const { app, host, name } = routeProps.match.params;
const appPath = `/ship/${host}/${name}`;
const association = associations.graph[appPath];
const resourceUrl = `${baseUrl}/join/${app}${appPath}`;
let title = groupAssociation?.metadata?.title ?? 'Groups';
if (!association) {
return <Loading />;
}
title += ` - ${association.metadata.title}`;
return (
<>
<Helmet defer={false}>
<title>{notificationsCount ? `(${String(notificationsCount)}) ` : ''}{ title }</title>
</Helmet>
return (
<Skeleton
recentGroups={recentGroups}
mobileHide
selected={appPath}
recentGroups={recentGroups}
selected={ship}
{...props}
baseUrl={baseUrl}
baseUrl={match.path}
> <DmResource ship={ship} />
</Skeleton>
);
}}
/>
<Route
path={[relativePath('/resource/:app/(ship)?/:host/:name')]}
render={(routeProps) => {
const { app, host, name } = routeProps.match.params as Record<
string,
string
>;
const resource = `/ship/${host}/${name}`;
const association = associations.graph[resource];
const resourceUrl = `${baseUrl}/resource/${app}${resource}`;
if (!association) {
return <Loading />;
}
return (
<Skeleton
mobileHide
recentGroups={recentGroups}
selected={resource}
{...props}
baseUrl={resourceUrl}
>
<UnjoinedResource
baseUrl={baseUrl}
<Resource
workspace={props.workspace}
association={association}
baseUrl={baseUrl}
/>
{popovers(routeProps, resourceUrl)}
</Skeleton>
</>
);
}}
/>
<Route
path={relativePath('/pending/:ship/:name')}
render={(routeProps) => {
const { ship, name } = routeProps.match.params as Record<string, string>;
const desc = {
group: `/ship/${ship}/${name}`,
kind: 'graph' as const
};
return (
<Skeleton
mobileHide
recentGroups={recentGroups}
{...props}
baseUrl={baseUrl}
>
<Box width="100%">
<Join desc={desc} />
</Box>
</Skeleton>
);
}}
/>
<Route
path={relativePath('/new')}
render={(routeProps) => {
return (
<Skeleton mobileHide recentGroups={recentGroups} {...props} baseUrl={baseUrl}>
<NewChannel
{...routeProps}
baseUrl={baseUrl}
group={groupPath}
workspace={workspace}
/>
{popovers(routeProps, baseUrl)}
</Skeleton>
);
}}
/>
<Route
path={[relativePath('/'), relativePath('/feed+')]}
render={(routeProps) => {
const shouldHideSidebar =
routeProps.location.pathname.includes('/feed');
const title = groupAssociation?.metadata?.title ?? 'Groups';
return (
<>
<Helmet defer={false}>
<title>
{notificationsCount ? `(${String(notificationsCount)}) ` : ''}
{ title }
</title>
</Helmet>
);
}}
/>
<Route
path={relativePath('/join/:app/(ship)?/:host/:name')}
render={(routeProps) => {
const { app, host, name } = routeProps.match.params;
const appPath = `/ship/${host}/${name}`;
const association = associations.graph[appPath];
const resourceUrl = `${baseUrl}/join/${app}${appPath}`;
let title = groupAssociation?.metadata?.title ?? 'Groups';
if (!association) {
return <Loading />;
}
title += ` - ${association.metadata.title}`;
return (
<>
<Helmet defer={false}>
<title>{notificationsCount ? `(${String(notificationsCount)}) ` : ''}{ title }</title>
</Helmet>
<Skeleton
recentGroups={recentGroups}
mobileHide
selected={appPath}
{...props}
baseUrl={baseUrl}
>
<UnjoinedResource
baseUrl={baseUrl}
association={association}
/>
{popovers(routeProps, resourceUrl)}
</Skeleton>
</>
);
}}
/>
<Route
path={relativePath('/pending/:ship/:name')}
render={(routeProps) => {
const { ship, name } = routeProps.match.params as Record<string, string>;
const desc = {
group: `/ship/${ship}/${name}`,
kind: 'graph' as const
};
return (
<Skeleton
{...props}
mobileHide={shouldHideSidebar}
mobileHide
recentGroups={recentGroups}
{...props}
baseUrl={baseUrl}
>
{ workspace.type === 'group' ? (
<GroupHome
baseUrl={baseUrl}
groupPath={groupPath}
/>
) : (
<EmptyGroupHome
associations={associations}
/>
)}
<Box width="100%">
<Join desc={desc} />
</Box>
</Skeleton>
);
}}
/>
<Route
path={relativePath('/new')}
render={(routeProps) => {
return (
<Skeleton mobileHide recentGroups={recentGroups} {...props} baseUrl={baseUrl}>
<NewChannel
{...routeProps}
baseUrl={baseUrl}
group={groupPath}
workspace={workspace}
/>
{popovers(routeProps, baseUrl)}
</Skeleton>
</>
);
}}
/>
</Switch>
);
}}
/>
<Route
path={[relativePath('/'), relativePath('/feed+')]}
render={(routeProps) => {
const shouldHideSidebar =
routeProps.location.pathname.includes('/feed');
const title = groupAssociation?.metadata?.title ?? 'Groups';
return (
<>
<Helmet defer={false}>
<title>
{notificationsCount ? `(${String(notificationsCount)}) ` : ''}
{ title }
</title>
</Helmet>
<Skeleton
{...props}
mobileHide={shouldHideSidebar}
recentGroups={recentGroups}
baseUrl={baseUrl}
>
{ workspace.type === 'group' ? (
<GroupHome
baseUrl={baseUrl}
groupPath={groupPath}
/>
) : (
<EmptyGroupHome
associations={associations}
/>
)}
{popovers(routeProps, baseUrl)}
</Skeleton>
</>
);
}}
/>
</Switch>
);
}