mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
refactor: abstract header adapter (#2580)
This commit is contained in:
@@ -34,14 +34,17 @@ import { z } from 'zod';
|
||||
|
||||
import { createAffineProviders } from '../../blocksuite';
|
||||
import { createAffineDownloadProvider } from '../../blocksuite/providers/affine';
|
||||
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
|
||||
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
|
||||
import { PageDetailEditor } from '../../components/page-detail-editor';
|
||||
import { PageLoading } from '../../components/pure/loading';
|
||||
import { useAffineRefreshAuthToken } from '../../hooks/affine/use-affine-refresh-auth-token';
|
||||
import { BlockSuiteWorkspace } from '../../shared';
|
||||
import { affineApis, affineAuth } from '../../shared/apis';
|
||||
import { toast } from '../../utils';
|
||||
import {
|
||||
BlockSuitePageList,
|
||||
PageDetailEditor,
|
||||
WorkspaceHeader,
|
||||
WorkspaceSettingDetail,
|
||||
} from '../shared';
|
||||
import type { WorkspaceAdapter } from '../type';
|
||||
import { QueryKey } from './fetcher';
|
||||
|
||||
@@ -311,6 +314,7 @@ export const AffineAdapter: WorkspaceAdapter<WorkspaceFlavour.AFFINE> = {
|
||||
</Suspense>
|
||||
);
|
||||
},
|
||||
Header: WorkspaceHeader,
|
||||
PageDetail: ({ currentWorkspace, currentPageId, onLoadEditor }) => {
|
||||
const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
|
||||
if (!page) {
|
||||
|
||||
@@ -17,32 +17,16 @@ import {
|
||||
} from '@affine/workspace/type';
|
||||
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
import { lazy } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
BlockSuitePageList,
|
||||
PageDetailEditor,
|
||||
WorkspaceHeader,
|
||||
WorkspaceSettingDetail,
|
||||
} from '../shared';
|
||||
import type { WorkspaceAdapter } from '../type';
|
||||
|
||||
const WorkspaceSettingDetail = lazy(() =>
|
||||
import('../../components/affine/workspace-setting-detail').then(
|
||||
({ WorkspaceSettingDetail }) => ({
|
||||
default: WorkspaceSettingDetail,
|
||||
})
|
||||
)
|
||||
);
|
||||
const BlockSuitePageList = lazy(() =>
|
||||
import('../../components/blocksuite/block-suite-page-list').then(
|
||||
({ BlockSuitePageList }) => ({
|
||||
default: BlockSuitePageList,
|
||||
})
|
||||
)
|
||||
);
|
||||
const PageDetailEditor = lazy(() =>
|
||||
import('../../components/page-detail-editor').then(
|
||||
({ PageDetailEditor }) => ({
|
||||
default: PageDetailEditor,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const logger = new DebugLogger('use-create-first-workspace');
|
||||
|
||||
export const LocalAdapter: WorkspaceAdapter<WorkspaceFlavour.LOCAL> = {
|
||||
@@ -78,6 +62,7 @@ export const LocalAdapter: WorkspaceAdapter<WorkspaceFlavour.LOCAL> = {
|
||||
},
|
||||
CRUD,
|
||||
UI: {
|
||||
Header: WorkspaceHeader,
|
||||
Provider: ({ children }) => {
|
||||
return <>{children}</>;
|
||||
},
|
||||
|
||||
27
apps/web/src/adapters/shared.ts
Normal file
27
apps/web/src/adapters/shared.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const WorkspaceSettingDetail = lazy(() =>
|
||||
import('../components/affine/workspace-setting-detail').then(
|
||||
({ WorkspaceSettingDetail }) => ({
|
||||
default: WorkspaceSettingDetail,
|
||||
})
|
||||
)
|
||||
);
|
||||
export const BlockSuitePageList = lazy(() =>
|
||||
import('../components/blocksuite/block-suite-page-list').then(
|
||||
({ BlockSuitePageList }) => ({
|
||||
default: BlockSuitePageList,
|
||||
})
|
||||
)
|
||||
);
|
||||
export const PageDetailEditor = lazy(() =>
|
||||
import('../components/page-detail-editor').then(({ PageDetailEditor }) => ({
|
||||
default: PageDetailEditor,
|
||||
}))
|
||||
);
|
||||
|
||||
export const WorkspaceHeader = lazy(() =>
|
||||
import('../components/workspace-header').then(({ WorkspaceHeader }) => ({
|
||||
default: WorkspaceHeader,
|
||||
}))
|
||||
);
|
||||
@@ -32,6 +32,7 @@ export const WorkspaceAdapters = {
|
||||
// todo: implement this
|
||||
UI: {
|
||||
Provider: unimplemented,
|
||||
Header: unimplemented,
|
||||
PageDetail: unimplemented,
|
||||
PageList: unimplemented,
|
||||
SettingsDetail: unimplemented,
|
||||
@@ -52,6 +53,7 @@ export const WorkspaceAdapters = {
|
||||
// todo: implement this
|
||||
UI: {
|
||||
Provider: unimplemented,
|
||||
Header: unimplemented,
|
||||
PageDetail: unimplemented,
|
||||
PageList: unimplemented,
|
||||
SettingsDetail: unimplemented,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
AffineLegacyCloudWorkspace,
|
||||
LocalWorkspace,
|
||||
} from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertEquals } from '@blocksuite/store';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -15,7 +15,6 @@ import { useCallback, useState } from 'react';
|
||||
import { useToggleWorkspacePublish } from '../../../../hooks/affine/use-toggle-workspace-publish';
|
||||
import { useOnTransformWorkspace } from '../../../../hooks/root/use-on-transform-workspace';
|
||||
import { useRouterHelper } from '../../../../hooks/use-router-helper';
|
||||
import { WorkspaceSubPath } from '../../../../shared';
|
||||
import { TransformWorkspaceToAffineModal } from '../../../affine/transform-workspace-to-affine-modal';
|
||||
import type { BaseHeaderProps } from '../header';
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ export type BaseHeaderProps<
|
||||
workspace: Workspace;
|
||||
currentPage: Page | null;
|
||||
isPublic: boolean;
|
||||
isPreview: boolean;
|
||||
leftSlot?: ReactNode;
|
||||
};
|
||||
|
||||
@@ -67,7 +66,6 @@ type HeaderItem = {
|
||||
currentPage: Page | null,
|
||||
status: {
|
||||
isPublic: boolean;
|
||||
isPreview: boolean;
|
||||
}
|
||||
) => boolean;
|
||||
};
|
||||
@@ -81,8 +79,8 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
|
||||
},
|
||||
[HeaderRightItemName.SyncUser]: {
|
||||
Component: SyncUser,
|
||||
availableWhen: (_, currentPage, { isPublic, isPreview }) => {
|
||||
return !isPublic && !isPreview;
|
||||
availableWhen: (_, currentPage, { isPublic }) => {
|
||||
return !isPublic;
|
||||
},
|
||||
},
|
||||
[HeaderRightItemName.ShareMenu]: {
|
||||
@@ -105,8 +103,8 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
|
||||
},
|
||||
[HeaderRightItemName.EditorOptionMenu]: {
|
||||
Component: EditorOptionMenu,
|
||||
availableWhen: (_, currentPage, { isPublic, isPreview }) => {
|
||||
return !isPublic && !isPreview;
|
||||
availableWhen: (_, currentPage, { isPublic }) => {
|
||||
return !isPublic;
|
||||
},
|
||||
},
|
||||
[HeaderRightItemName.WindowsAppControls]: {
|
||||
@@ -216,7 +214,6 @@ export const Header = forwardRef<
|
||||
([name, { availableWhen, Component }]) => {
|
||||
if (
|
||||
availableWhen(props.workspace, props.currentPage, {
|
||||
isPreview: props.isPreview,
|
||||
isPublic: props.isPublic,
|
||||
})
|
||||
) {
|
||||
@@ -224,7 +221,6 @@ export const Header = forwardRef<
|
||||
<Component
|
||||
workspace={props.workspace}
|
||||
currentPage={props.currentPage}
|
||||
isPreview={props.isPreview}
|
||||
isPublic={props.isPublic}
|
||||
key={name}
|
||||
/>
|
||||
|
||||
@@ -18,7 +18,7 @@ import * as styles from './styles.css';
|
||||
|
||||
export type WorkspaceHeaderProps = BaseHeaderProps;
|
||||
|
||||
export const WorkspaceHeader: FC<
|
||||
export const BlockSuiteEditorHeader: FC<
|
||||
PropsWithChildren<WorkspaceHeaderProps> & HTMLAttributes<HTMLDivElement>
|
||||
> = (props): ReactElement => {
|
||||
const { workspace, currentPage, children, isPublic } = props;
|
||||
@@ -62,4 +62,4 @@ export const WorkspaceHeader: FC<
|
||||
);
|
||||
};
|
||||
|
||||
WorkspaceHeader.displayName = 'BlockSuiteEditorHeader';
|
||||
BlockSuiteEditorHeader.displayName = 'BlockSuiteEditorHeader';
|
||||
|
||||
@@ -13,16 +13,13 @@ import { startTransition, useCallback } from 'react';
|
||||
import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms';
|
||||
import type { AffineOfficialWorkspace } from '../shared';
|
||||
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
|
||||
import { WorkspaceHeader } from './blocksuite/workspace-header';
|
||||
|
||||
export type PageDetailEditorProps = {
|
||||
isPublic?: boolean;
|
||||
isPreview?: boolean;
|
||||
workspace: AffineOfficialWorkspace;
|
||||
pageId: string;
|
||||
onInit: (page: Page, editor: Readonly<EditorContainer>) => void;
|
||||
onLoad?: (page: Page, editor: EditorContainer) => () => void;
|
||||
header?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
|
||||
@@ -30,9 +27,7 @@ export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
|
||||
pageId,
|
||||
onInit,
|
||||
onLoad,
|
||||
header,
|
||||
isPublic,
|
||||
isPreview,
|
||||
}) => {
|
||||
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
||||
@@ -52,14 +47,6 @@ export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
<WorkspaceHeader
|
||||
isPublic={isPublic ?? false}
|
||||
isPreview={isPreview ?? false}
|
||||
workspace={workspace}
|
||||
currentPage={page}
|
||||
>
|
||||
{header}
|
||||
</WorkspaceHeader>
|
||||
<Editor
|
||||
style={{
|
||||
height: 'calc(100% - 52px)',
|
||||
|
||||
127
apps/web/src/components/workspace-header.tsx
Normal file
127
apps/web/src/components/workspace-header.tsx
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Button } from '@affine/component';
|
||||
import {
|
||||
FilterList,
|
||||
SaveViewButton,
|
||||
useAllPageSetting,
|
||||
ViewList,
|
||||
} from '@affine/component/page-list';
|
||||
import { config } from '@affine/env';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { WorkspaceHeaderProps } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import {
|
||||
DeleteTemporarilyIcon,
|
||||
FolderIcon,
|
||||
SettingsIcon,
|
||||
ShareIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import type { ReactElement } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import { BlockSuiteEditorHeader } from './blocksuite/workspace-header';
|
||||
import { WorkspaceTitle } from './pure/workspace-title';
|
||||
|
||||
export function WorkspaceHeader({
|
||||
currentWorkspace,
|
||||
currentEntry,
|
||||
}: WorkspaceHeaderProps<WorkspaceFlavour>): ReactElement {
|
||||
const setting = useAllPageSetting();
|
||||
const t = useAFFiNEI18N();
|
||||
if ('subPath' in currentEntry) {
|
||||
if (currentEntry.subPath === WorkspaceSubPath.ALL) {
|
||||
const leftSlot = config.enableAllPageFilter && (
|
||||
<ViewList setting={setting}></ViewList>
|
||||
);
|
||||
const filterContainer = config.enableAllPageFilter &&
|
||||
setting.currentView.filterList.length > 0 && (
|
||||
<div style={{ padding: 12, display: 'flex' }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<FilterList
|
||||
value={setting.currentView.filterList}
|
||||
onChange={filterList =>
|
||||
setting.changeView(
|
||||
{
|
||||
...setting.currentView,
|
||||
filterList,
|
||||
},
|
||||
setting.currentViewIndex
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{setting.currentViewIndex == null ? (
|
||||
<SaveViewButton
|
||||
init={setting.currentView.filterList}
|
||||
onConfirm={setting.createView}
|
||||
></SaveViewButton>
|
||||
) : (
|
||||
<Button onClick={() => setting.selectView()}>
|
||||
Back to all
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPublic={false}
|
||||
icon={<FolderIcon />}
|
||||
leftSlot={leftSlot}
|
||||
>
|
||||
{t['All pages']()}
|
||||
</WorkspaceTitle>
|
||||
{filterContainer}
|
||||
</>
|
||||
);
|
||||
} else if (currentEntry.subPath === WorkspaceSubPath.SETTING) {
|
||||
return (
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPublic={false}
|
||||
icon={<SettingsIcon />}
|
||||
>
|
||||
{t['Workspace Settings']()}
|
||||
</WorkspaceTitle>
|
||||
);
|
||||
} else if (currentEntry.subPath === WorkspaceSubPath.SHARED) {
|
||||
return (
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPublic={false}
|
||||
icon={<ShareIcon />}
|
||||
>
|
||||
{t['Shared Pages']()}
|
||||
</WorkspaceTitle>
|
||||
);
|
||||
} else if (currentEntry.subPath === WorkspaceSubPath.TRASH) {
|
||||
return (
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPublic={false}
|
||||
icon={<DeleteTemporarilyIcon />}
|
||||
>
|
||||
{t['Trash']()}
|
||||
</WorkspaceTitle>
|
||||
);
|
||||
}
|
||||
} else if ('pageId' in currentEntry) {
|
||||
const pageId = currentEntry.pageId;
|
||||
const isPublic = currentWorkspace.flavour === WorkspaceFlavour.PUBLIC;
|
||||
return (
|
||||
<BlockSuiteEditorHeader
|
||||
isPublic={isPublic}
|
||||
workspace={currentWorkspace}
|
||||
currentPage={currentWorkspace.blockSuiteWorkspace.getPage(pageId)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <></>;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import 'fake-indexeddb/auto';
|
||||
import assert from 'node:assert';
|
||||
|
||||
import { rootCurrentWorkspaceIdAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import type { PageBlockModel } from '@blocksuite/blocks';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
@@ -23,7 +23,7 @@ import type React from 'react';
|
||||
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { workspacesAtom } from '../../atoms';
|
||||
import { BlockSuiteWorkspace, WorkspaceSubPath } from '../../shared';
|
||||
import { BlockSuiteWorkspace } from '../../shared';
|
||||
import {
|
||||
currentWorkspaceAtom,
|
||||
useCurrentWorkspace,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
rootWorkspacesMetadataAtom,
|
||||
} from '@affine/workspace/atom';
|
||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||
import { WorkspaceFlavour, WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
@@ -21,7 +21,6 @@ import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import { LocalAdapter } from '../../adapters/local';
|
||||
import { workspacesAtom } from '../../atoms';
|
||||
import { BlockSuiteWorkspace } from '../../shared';
|
||||
import { WorkspaceSubPath } from '../../shared';
|
||||
import {
|
||||
currentWorkspaceAtom,
|
||||
useCurrentWorkspace,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* @vitest-environment happy-dom
|
||||
*/
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import routerMock from 'next-router-mock';
|
||||
import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
|
||||
import { beforeAll, describe, expect, test } from 'vitest';
|
||||
|
||||
import { WorkspaceSubPath } from '../../shared';
|
||||
import { RouteLogic, useRouterHelper } from '../use-router-helper';
|
||||
|
||||
beforeAll(() => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import type { NextRouter } from 'next/router';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import type { WorkspaceSubPath } from '../shared';
|
||||
|
||||
export const enum RouteLogic {
|
||||
REPLACE = 'replace',
|
||||
PUSH = 'push',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import type { NextPage } from 'next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
@@ -6,7 +7,6 @@ import { Suspense, useEffect } from 'react';
|
||||
import { PageLoading } from '../components/pure/loading';
|
||||
import { RouteLogic, useRouterHelper } from '../hooks/use-router-helper';
|
||||
import { useAppHelper, useWorkspaces } from '../hooks/use-workspaces';
|
||||
import { WorkspaceSubPath } from '../shared';
|
||||
|
||||
const logger = new DebugLogger('index-page');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { displayFlex, styled } from '@affine/component';
|
||||
import { Button } from '@affine/component';
|
||||
import type { Permission } from '@affine/workspace/affine/api';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import {
|
||||
SucessfulDuotoneIcon,
|
||||
UnsucessfulDuotoneIcon,
|
||||
@@ -15,7 +16,6 @@ import { QueryKey } from '../../adapters/affine/fetcher';
|
||||
import { PageLoading } from '../../components/pure/loading';
|
||||
import { RouteLogic, useRouterHelper } from '../../hooks/use-router-helper';
|
||||
import type { NextPageWithLayout } from '../../shared';
|
||||
import { WorkspaceSubPath } from '../../shared';
|
||||
|
||||
const InvitePage: NextPageWithLayout = () => {
|
||||
const router = useRouter();
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
publicWorkspaceIdAtom,
|
||||
publicWorkspacePageIdAtom,
|
||||
} from '../../../atoms/public-workspace';
|
||||
import { BlockSuiteEditorHeader } from '../../../components/blocksuite/workspace-header';
|
||||
import { PageDetailEditor } from '../../../components/page-detail-editor';
|
||||
import { WorkspaceAvatar } from '../../../components/pure/footer';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
@@ -70,6 +71,28 @@ const PublicWorkspaceDetailPageInner = (): ReactElement => {
|
||||
return (
|
||||
<>
|
||||
<PublicQuickSearch workspace={publicWorkspace} />
|
||||
<BlockSuiteEditorHeader
|
||||
isPublic={true}
|
||||
workspace={publicWorkspace}
|
||||
currentPage={blockSuiteWorkspace.getPage(pageId)}
|
||||
>
|
||||
<NavContainer>
|
||||
<Breadcrumbs>
|
||||
<StyledBreadcrumbs
|
||||
href={`/public-workspace/${blockSuiteWorkspace.id}`}
|
||||
>
|
||||
<WorkspaceAvatar size={24} name={name} avatar={avatar} />
|
||||
<span>{name}</span>
|
||||
</StyledBreadcrumbs>
|
||||
<StyledBreadcrumbs
|
||||
href={`/public-workspace/${blockSuiteWorkspace.id}/${pageId}`}
|
||||
>
|
||||
<PageIcon fontSize={24} />
|
||||
<span>{pageTitle ? pageTitle : t['Untitled']()}</span>
|
||||
</StyledBreadcrumbs>
|
||||
</Breadcrumbs>
|
||||
</NavContainer>
|
||||
</BlockSuiteEditorHeader>
|
||||
<PageDetailEditor
|
||||
isPublic={true}
|
||||
pageId={pageId}
|
||||
@@ -85,24 +108,6 @@ const PublicWorkspaceDetailPageInner = (): ReactElement => {
|
||||
};
|
||||
}}
|
||||
onInit={initPage}
|
||||
header={
|
||||
<NavContainer>
|
||||
<Breadcrumbs>
|
||||
<StyledBreadcrumbs
|
||||
href={`/public-workspace/${blockSuiteWorkspace.id}`}
|
||||
>
|
||||
<WorkspaceAvatar size={24} name={name} avatar={avatar} />
|
||||
<span>{name}</span>
|
||||
</StyledBreadcrumbs>
|
||||
<StyledBreadcrumbs
|
||||
href={`/public-workspace/${blockSuiteWorkspace.id}/${pageId}`}
|
||||
>
|
||||
<PageIcon fontSize={24} />
|
||||
<span>{pageTitle ? pageTitle : t['Untitled']()}</span>
|
||||
</StyledBreadcrumbs>
|
||||
</Breadcrumbs>
|
||||
</NavContainer>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -56,13 +56,21 @@ const WorkspaceDetail: React.FC = () => {
|
||||
}
|
||||
}, [currentWorkspace]);
|
||||
|
||||
const { PageDetail } = getUIAdapter(currentWorkspace.flavour);
|
||||
const { PageDetail, Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
return (
|
||||
<PageDetail
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentPageId={currentPageId}
|
||||
onLoadEditor={onLoad}
|
||||
/>
|
||||
<>
|
||||
<Header
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentEntry={{
|
||||
pageId: currentPageId,
|
||||
}}
|
||||
/>
|
||||
<PageDetail
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentPageId={currentPageId}
|
||||
onLoadEditor={onLoad}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { Button } from '@affine/component';
|
||||
import {
|
||||
FilterList,
|
||||
SaveViewButton,
|
||||
useAllPageSetting,
|
||||
ViewList,
|
||||
} from '@affine/component/page-list';
|
||||
import { config } from '@affine/env';
|
||||
import { useAllPageSetting } from '@affine/component/page-list';
|
||||
import { QueryParamError } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { FolderIcon } from '@blocksuite/icons';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -16,7 +9,6 @@ import React, { useCallback } from 'react';
|
||||
|
||||
import { getUIAdapter } from '../../../adapters/workspace';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useRouterHelper } from '../../../hooks/use-router-helper';
|
||||
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||
@@ -45,56 +37,19 @@ const AllPage: NextPageWithLayout = () => {
|
||||
if (typeof router.query.workspaceId !== 'string') {
|
||||
throw new QueryParamError('workspaceId', router.query.workspaceId);
|
||||
}
|
||||
const leftSlot = config.enableAllPageFilter && (
|
||||
<ViewList setting={setting}></ViewList>
|
||||
);
|
||||
const filterContainer = config.enableAllPageFilter &&
|
||||
setting.currentView.filterList.length > 0 && (
|
||||
<div style={{ padding: 12, display: 'flex' }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<FilterList
|
||||
value={setting.currentView.filterList}
|
||||
onChange={filterList =>
|
||||
setting.changeView(
|
||||
{
|
||||
...setting.currentView,
|
||||
filterList,
|
||||
},
|
||||
setting.currentViewIndex
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{setting.currentViewIndex == null ? (
|
||||
<SaveViewButton
|
||||
init={setting.currentView.filterList}
|
||||
onConfirm={setting.createView}
|
||||
></SaveViewButton>
|
||||
) : (
|
||||
<Button onClick={() => setting.selectView()}>Back to all</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const { PageList } = getUIAdapter(currentWorkspace.flavour);
|
||||
const { PageList, Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t['All pages']()} - AFFiNE</title>
|
||||
</Head>
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPreview={false}
|
||||
isPublic={false}
|
||||
icon={<FolderIcon />}
|
||||
leftSlot={leftSlot}
|
||||
>
|
||||
{t['All pages']()}
|
||||
</WorkspaceTitle>
|
||||
{filterContainer}
|
||||
<Header
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentEntry={{
|
||||
subPath: WorkspaceSubPath.ALL,
|
||||
}}
|
||||
/>
|
||||
<PageList
|
||||
view={setting.currentView}
|
||||
onOpenPage={onClickPage}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
|
||||
import type { SettingPanel } from '@affine/workspace/type';
|
||||
import { settingPanel, settingPanelValues } from '@affine/workspace/type';
|
||||
import { SettingsIcon } from '@blocksuite/icons';
|
||||
import {
|
||||
settingPanel,
|
||||
settingPanelValues,
|
||||
WorkspaceSubPath,
|
||||
} from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
@@ -13,7 +16,6 @@ import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
import { getUIAdapter } from '../../../adapters/workspace';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useOnTransformWorkspace } from '../../../hooks/root/use-on-transform-workspace';
|
||||
import { useAppHelper } from '../../../hooks/use-workspaces';
|
||||
@@ -115,21 +117,18 @@ const SettingPage: NextPageWithLayout = () => {
|
||||
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
const { SettingsDetail } = getUIAdapter(currentWorkspace.flavour);
|
||||
const { SettingsDetail, Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t['Settings']()} - AFFiNE</title>
|
||||
</Head>
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPreview={false}
|
||||
isPublic={false}
|
||||
icon={<SettingsIcon />}
|
||||
>
|
||||
{t['Workspace Settings']()}
|
||||
</WorkspaceTitle>
|
||||
<Header
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentEntry={{
|
||||
subPath: WorkspaceSubPath.SETTING,
|
||||
}}
|
||||
/>
|
||||
<SettingsDetail
|
||||
onTransformWorkspace={onTransformWorkspace}
|
||||
onDeleteWorkspace={onDeleteWorkspace}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ShareIcon } from '@blocksuite/icons';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { getUIAdapter } from '../../../adapters/workspace';
|
||||
import { BlockSuitePageList } from '../../../components/blocksuite/block-suite-page-list';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useRouterHelper } from '../../../hooks/use-router-helper';
|
||||
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||
import type { NextPageWithLayout } from '../../../shared';
|
||||
|
||||
const SharedPages: NextPageWithLayout = () => {
|
||||
const router = useRouter();
|
||||
const { jumpToPage } = useRouterHelper(router);
|
||||
@@ -34,20 +33,18 @@ const SharedPages: NextPageWithLayout = () => {
|
||||
}
|
||||
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace;
|
||||
assertExists(blockSuiteWorkspace);
|
||||
const { Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t['Shared Pages']()} - AFFiNE</title>
|
||||
</Head>
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPreview={false}
|
||||
isPublic={false}
|
||||
icon={<ShareIcon />}
|
||||
>
|
||||
{t['Shared Pages']()}
|
||||
</WorkspaceTitle>
|
||||
<Header
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentEntry={{
|
||||
subPath: WorkspaceSubPath.SHARED,
|
||||
}}
|
||||
/>
|
||||
<BlockSuitePageList
|
||||
blockSuiteWorkspace={blockSuiteWorkspace}
|
||||
onOpenPage={onClickPage}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { DeleteTemporarilyIcon } from '@blocksuite/icons';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { getUIAdapter } from '../../../adapters/workspace';
|
||||
import { BlockSuitePageList } from '../../../components/blocksuite/block-suite-page-list';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||
import { useRouterHelper } from '../../../hooks/use-router-helper';
|
||||
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||
@@ -37,20 +37,18 @@ const TrashPage: NextPageWithLayout = () => {
|
||||
// todo(himself65): refactor to plugin
|
||||
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace;
|
||||
assertExists(blockSuiteWorkspace);
|
||||
const { Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t['Trash']()} - AFFiNE</title>
|
||||
</Head>
|
||||
<WorkspaceTitle
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPreview={false}
|
||||
isPublic={false}
|
||||
icon={<DeleteTemporarilyIcon />}
|
||||
>
|
||||
{t['Trash']()}
|
||||
</WorkspaceTitle>
|
||||
<Header
|
||||
currentWorkspace={currentWorkspace}
|
||||
currentEntry={{
|
||||
subPath: WorkspaceSubPath.TRASH,
|
||||
}}
|
||||
/>
|
||||
<BlockSuitePageList
|
||||
blockSuiteWorkspace={blockSuiteWorkspace}
|
||||
onOpenPage={onClickPage}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getEnvironment } from '@affine/env';
|
||||
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { arrayMove } from '@dnd-kit/sortable';
|
||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||
import { useRouter } from 'next/router';
|
||||
@@ -19,7 +20,6 @@ import { useCurrentUser } from '../hooks/current/use-current-user';
|
||||
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
||||
import { useRouterHelper } from '../hooks/use-router-helper';
|
||||
import { useWorkspaces } from '../hooks/use-workspaces';
|
||||
import { WorkspaceSubPath } from '../shared';
|
||||
|
||||
const WorkspaceListModal = lazy(() =>
|
||||
import('../components/pure/workspace-list-modal').then(module => ({
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
} from '@affine/workspace/type';
|
||||
import type { AffinePublicWorkspace } from '@affine/workspace/type';
|
||||
import type { WorkspaceRegistry } from '@affine/workspace/type';
|
||||
import { WorkspaceSubPath } from '@affine/workspace/type';
|
||||
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
|
||||
import type { NextPage } from 'next';
|
||||
import type { ReactElement, ReactNode } from 'react';
|
||||
@@ -24,13 +25,6 @@ export type NextPageWithLayout<P = Record<string, unknown>, IP = P> = NextPage<
|
||||
getLayout?: (page: ReactElement) => ReactNode;
|
||||
};
|
||||
|
||||
export const enum WorkspaceSubPath {
|
||||
ALL = 'all',
|
||||
SETTING = 'setting',
|
||||
TRASH = 'trash',
|
||||
SHARED = 'shared',
|
||||
}
|
||||
|
||||
export const WorkspaceSubPathName = {
|
||||
[WorkspaceSubPath.ALL]: 'All Pages',
|
||||
[WorkspaceSubPath.SETTING]: 'Settings',
|
||||
|
||||
Reference in New Issue
Block a user