refactor: lazy load workspaces (#3091)

This commit is contained in:
Alex Yang
2023-07-07 22:15:27 +08:00
committed by GitHub
parent 66152401be
commit 283f0cd263
45 changed files with 446 additions and 750 deletions

View File

@@ -1,4 +1,4 @@
import { Skeleton } from '@mui/material';
import { NoSsr, Skeleton } from '@mui/material';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import { useAtom, useAtomValue } from 'jotai';
@@ -107,7 +107,9 @@ export function AppSidebar(props: AppSidebarProps): ReactElement {
data-enable-animation={enableAnimation && !isResizing}
>
<nav className={navStyle} ref={navRef} data-testid="app-sidebar">
<SidebarHeader router={props.router} />
<NoSsr>
<SidebarHeader router={props.router} />
</NoSsr>
<div className={navBodyStyle} data-testid="sliderBar-inner">
{props.children}
</div>

View File

@@ -1,10 +1,14 @@
import type {
AffineCloudWorkspace,
LocalWorkspace,
} from '@affine/env/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { RootWorkspaceMetadata } from '@affine/workspace/atom';
import { useStaticBlockSuiteWorkspace } from '@affine/workspace/utils';
import { SettingsIcon } from '@blocksuite/icons';
import {
CloudWorkspaceIcon as DefaultCloudWorkspaceIcon,
CollaborationIcon as DefaultJoinedWorkspaceIcon,
LocalDataIcon as DefaultLocalDataIcon,
LocalWorkspaceIcon as DefaultLocalWorkspaceIcon,
} from '@blocksuite/icons';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
import type { FC } from 'react';
import { useCallback } from 'react';
@@ -18,16 +22,8 @@ import {
} from './styles';
export type WorkspaceTypeProps = {
workspace: AffineCloudWorkspace | LocalWorkspace;
flavour: WorkspaceFlavour;
};
import {
CloudWorkspaceIcon as DefaultCloudWorkspaceIcon,
CollaborationIcon as DefaultJoinedWorkspaceIcon,
LocalDataIcon as DefaultLocalDataIcon,
LocalWorkspaceIcon as DefaultLocalWorkspaceIcon,
} from '@blocksuite/icons';
const JoinedWorkspaceIcon = () => {
return <DefaultJoinedWorkspaceIcon style={{ color: '#FF646B' }} />;
};
@@ -43,12 +39,12 @@ const LocalDataIcon = () => {
return <DefaultLocalDataIcon style={{ color: '#62CD80' }} />;
};
const WorkspaceType: FC<WorkspaceTypeProps> = ({ workspace }) => {
const WorkspaceType: FC<WorkspaceTypeProps> = ({ flavour }) => {
const t = useAFFiNEI18N();
// fixme: cloud regression
const isOwner = true;
if (workspace.flavour === WorkspaceFlavour.LOCAL) {
if (flavour === WorkspaceFlavour.LOCAL) {
return (
<p title={t['Local Workspace']()}>
<LocalWorkspaceIcon />
@@ -72,51 +68,46 @@ const WorkspaceType: FC<WorkspaceTypeProps> = ({ workspace }) => {
export type WorkspaceCardProps = {
currentWorkspaceId: string | null;
workspace: AffineCloudWorkspace | LocalWorkspace;
onClick: (workspace: AffineCloudWorkspace | LocalWorkspace) => void;
onSettingClick: (workspace: AffineCloudWorkspace | LocalWorkspace) => void;
meta: RootWorkspaceMetadata;
onClick: (workspaceId: string) => void;
onSettingClick: (workspaceId: string) => void;
};
export const WorkspaceCard: FC<WorkspaceCardProps> = ({
workspace,
onClick,
onSettingClick,
currentWorkspaceId,
meta,
}) => {
const t = useAFFiNEI18N();
const [name] = useBlockSuiteWorkspaceName(workspace.blockSuiteWorkspace);
const workspace = useStaticBlockSuiteWorkspace(meta.id);
const [name] = useBlockSuiteWorkspaceName(workspace);
return (
<StyledCard
data-testid="workspace-card"
onClick={useCallback(() => {
onClick(workspace);
}, [onClick, workspace])}
onClick(meta.id);
}, [onClick, meta.id])}
active={workspace.id === currentWorkspaceId}
>
<WorkspaceAvatar size={58} workspace={workspace} />
<StyleWorkspaceInfo>
<StyleWorkspaceTitle>{name}</StyleWorkspaceTitle>
<WorkspaceType workspace={workspace} />
{workspace.flavour === WorkspaceFlavour.LOCAL && (
<WorkspaceType flavour={meta.flavour} />
{meta.flavour === WorkspaceFlavour.LOCAL && (
<p title={t['Available Offline']()}>
<LocalDataIcon />
<span>{t['Available Offline']()}</span>
</p>
)}
{/* {workspace.flavour === WorkspaceFlavour.AFFINE && workspace.public && (
<p title={t['Published to Web']()}>
<PublishIcon />
<span>{t['Published to Web']()}</span>
</p>
)} */}
</StyleWorkspaceInfo>
<StyledSettingLink
className="setting-entry"
onClick={e => {
e.stopPropagation();
onSettingClick(workspace);
onSettingClick(meta.id);
}}
>
<SettingsIcon />

View File

@@ -1,8 +1,3 @@
import type {
AffineCloudWorkspace,
AffinePublicWorkspace,
LocalWorkspace,
} from '@affine/env/workspace';
import type { Workspace } from '@blocksuite/store';
import * as RadixAvatar from '@radix-ui/react-avatar';
import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-suite-workspace-avatar-url';
@@ -15,11 +10,7 @@ import { avatarImageStyle, avatarStyle } from './index.css';
export type WorkspaceAvatarProps = {
size?: number;
workspace:
| AffineCloudWorkspace
| LocalWorkspace
| AffinePublicWorkspace
| null;
workspace: Workspace | null;
className?: string;
};
@@ -60,13 +51,9 @@ export const WorkspaceAvatar: React.FC<WorkspaceAvatarProps> = ({
workspace,
...props
}) => {
if (workspace && 'blockSuiteWorkspace' in workspace) {
if (workspace) {
return (
<BlockSuiteWorkspaceAvatar
{...props}
size={size}
workspace={workspace.blockSuiteWorkspace}
/>
<BlockSuiteWorkspaceAvatar {...props} size={size} workspace={workspace} />
);
}
return (

View File

@@ -2,6 +2,7 @@ import type {
AffineCloudWorkspace,
LocalWorkspace,
} from '@affine/env/workspace';
import type { RootWorkspaceMetadata } from '@affine/workspace/atom';
import type { DragEndEvent } from '@dnd-kit/core';
import {
DndContext,
@@ -10,7 +11,8 @@ import {
useSensors,
} from '@dnd-kit/core';
import { SortableContext, useSortable } from '@dnd-kit/sortable';
import type { FC } from 'react';
import type { CSSProperties, FC } from 'react';
import { useMemo } from 'react';
import { WorkspaceCard } from '../../components/card/workspace-card';
import { workspaceItemStyle } from './index.css';
@@ -19,26 +21,29 @@ export type WorkspaceListProps = {
disabled?: boolean;
currentWorkspaceId: string | null;
items: (AffineCloudWorkspace | LocalWorkspace)[];
onClick: (workspace: AffineCloudWorkspace | LocalWorkspace) => void;
onSettingClick: (workspace: AffineCloudWorkspace | LocalWorkspace) => void;
onClick: (workspaceId: string) => void;
onSettingClick: (workspaceId: string) => void;
onDragEnd: (event: DragEndEvent) => void;
};
const SortableWorkspaceItem: FC<
Omit<WorkspaceListProps, 'items'> & {
item: AffineCloudWorkspace | LocalWorkspace;
item: RootWorkspaceMetadata;
}
> = props => {
const { setNodeRef, attributes, listeners, transform } = useSortable({
id: props.item.id,
});
const style: React.CSSProperties = {
transform: transform
? `translate3d(${transform.x}px, ${transform.y}px, 0)`
: undefined,
pointerEvents: props.disabled ? 'none' : undefined,
opacity: props.disabled ? 0.6 : undefined,
};
const style: CSSProperties = useMemo(
() => ({
transform: transform
? `translate3d(${transform.x}px, ${transform.y}px, 0)`
: undefined,
pointerEvents: props.disabled ? 'none' : undefined,
opacity: props.disabled ? 0.6 : undefined,
}),
[props.disabled, transform]
);
return (
<div
className={workspaceItemStyle}
@@ -50,7 +55,7 @@ const SortableWorkspaceItem: FC<
>
<WorkspaceCard
currentWorkspaceId={props.currentWorkspaceId}
workspace={props.item}
meta={props.item}
onClick={props.onClick}
onSettingClick={props.onSettingClick}
/>

View File

@@ -1,8 +1,10 @@
import type { TooltipProps } from '@mui/material';
import { NoSsr } from '@mui/material';
import { styled } from '../../styles';
import { Popper, type PopperProps } from '../popper';
import StyledPopperContainer from '../shared/container';
const StyledTooltip = styled(StyledPopperContainer)(() => {
return {
maxWidth: '320px',
@@ -19,11 +21,13 @@ const StyledTooltip = styled(StyledPopperContainer)(() => {
export const Tooltip = (props: PopperProps & Omit<TooltipProps, 'title'>) => {
const { content, placement = 'top-start', children } = props;
return (
<Popper
{...props}
content={<StyledTooltip placement={placement}>{content}</StyledTooltip>}
>
{children}
</Popper>
<NoSsr>
<Popper
{...props}
content={<StyledTooltip placement={placement}>{content}</StyledTooltip>}
>
{children}
</Popper>
</NoSsr>
);
};