pengx17
2024-05-31 10:28:37 +00:00
parent b65c01c5e1
commit ea0059fa1b
31 changed files with 1018 additions and 44 deletions
@@ -1,10 +1,12 @@
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useJournalHelper } from '@affine/core/hooks/use-journal';
import { PeekViewService } from '@affine/core/modules/peek-view';
import { WorkbenchLink } from '@affine/core/modules/workbench';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { LinkedPageIcon, TodayIcon } from '@blocksuite/icons';
import type { DocCollection } from '@blocksuite/store';
import type { PropsWithChildren } from 'react';
import { useService } from '@toeverything/infra';
import { type PropsWithChildren, useCallback, useRef } from 'react';
import * as styles from './styles.css';
@@ -64,8 +66,30 @@ export function AffinePageReference({
t,
});
const ref = useRef<HTMLAnchorElement>(null);
const peekView = useService(PeekViewService).peekView;
const onClick = useCallback(
(e: React.MouseEvent) => {
if (e.shiftKey && ref.current) {
e.preventDefault();
e.stopPropagation();
peekView.open(ref.current);
return true; // means this click is handled
}
return false;
},
[peekView]
);
return (
<WorkbenchLink to={`/${pageId}`} className={styles.pageReferenceLink}>
<WorkbenchLink
ref={ref}
to={`/${pageId}`}
onClick={onClick}
className={styles.pageReferenceLink}
>
{Wrapper ? <Wrapper>{el}</Wrapper> : el}
</WorkbenchLink>
);
@@ -2,7 +2,6 @@ import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const linkItemRoot = style({
color: 'inherit',
display: 'contents',
});
export const root = style({
display: 'inline-flex',
@@ -19,7 +19,7 @@ export interface MenuItemProps extends React.HTMLAttributes<HTMLDivElement> {
export interface MenuLinkItemProps extends MenuItemProps {
to: To;
linkComponent?: React.ComponentType<{ to: To; className: string }>;
linkComponent?: React.ComponentType<{ to: To; className?: string }>;
}
const stopPropagation: React.MouseEventHandler = e => {
@@ -4,6 +4,7 @@ import {
useLitPortalFactory,
} from '@affine/component';
import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import { PeekViewService } from '@affine/core/modules/peek-view';
import { WorkbenchService } from '@affine/core/modules/workbench';
import type { BlockSpec } from '@blocksuite/block-std';
import {
@@ -30,6 +31,7 @@ import { AffinePageReference } from '../../affine/reference-link';
import { BlocksuiteEditorJournalDocTitle } from './journal-doc-title';
import {
patchNotificationService,
patchPeekViewService,
patchReferenceRenderer,
type ReferenceReactRenderer,
} from './specs/custom/spec-patchers';
@@ -66,6 +68,7 @@ interface BlocksuiteEditorProps {
const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
const [reactToLit, portals] = useLitPortalFactory();
const peekViewService = useService(PeekViewService);
const referenceRenderer: ReferenceReactRenderer = useMemo(() => {
return function customReference(reference) {
const pageId = reference.delta.attributes?.reference?.pageId;
@@ -83,8 +86,9 @@ const usePatchSpecs = (page: Doc, specs: BlockSpec[]) => {
patchReferenceRenderer(patched, reactToLit, referenceRenderer),
confirmModal
);
patched = patchPeekViewService(patched, peekViewService);
return patched;
}, [confirmModal, reactToLit, referenceRenderer, specs]);
}, [confirmModal, peekViewService, reactToLit, referenceRenderer, specs]);
return [
patchedSpecs,
@@ -6,6 +6,9 @@ import {
type ToastOptions,
type useConfirmModal,
} from '@affine/component';
import type { PeekViewService } from '@affine/core/modules/peek-view';
import type { ActivePeekView } from '@affine/core/modules/peek-view/entities/peek-view';
import { DebugLogger } from '@affine/debug';
import type { BlockSpec } from '@blocksuite/block-std';
import type {
AffineReference,
@@ -15,6 +18,8 @@ import type {
import { LitElement, type TemplateResult } from 'lit';
import React, { createElement, type ReactNode } from 'react';
const logger = new DebugLogger('affine::spec-patchers');
export type ReferenceReactRenderer = (
reference: AffineReference
) => React.ReactElement;
@@ -190,3 +195,27 @@ export function patchNotificationService(
});
return specs;
}
export function patchPeekViewService(
specs: BlockSpec[],
service: PeekViewService
) {
const rootSpec = specs.find(
spec => spec.schema.model.flavour === 'affine:page'
) as BlockSpec<string, RootService>;
if (!rootSpec) {
return specs;
}
patchSpecService(rootSpec, pageService => {
pageService.peekViewService = {
peek: (target: ActivePeekView['target']) => {
logger.debug('center peek', target);
service.peekView.open(target);
},
};
});
return specs;
}
@@ -18,6 +18,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
DeleteIcon,
DeletePermanentlyIcon,
DualLinkIcon,
DuplicateIcon,
EditIcon,
FavoritedIcon,
@@ -25,7 +26,6 @@ import {
FilterIcon,
FilterMinusIcon,
MoreVerticalIcon,
OpenInNewIcon,
PlusIcon,
ResetIcon,
SplitViewIcon,
@@ -170,7 +170,7 @@ export const PageOperationCell = ({
style={{ marginBottom: 4 }}
preFix={
<MenuIcon>
<OpenInNewIcon />
<DualLinkIcon />
</MenuIcon>
}
>
@@ -231,7 +231,7 @@ export const CollectionSidebarNavItem = ({
<span>{collection.name}</span>
</SidebarMenuLinkItem>
<Collapsible.Content className={styles.collapsibleContent}>
<div style={{ marginLeft: 20, marginTop: -4 }}>
<div className={styles.docsListContainer}>
{pagesToRender.map(page => {
return (
<Doc
@@ -1,19 +1,21 @@
import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references';
import { WorkbenchService } from '@affine/core/modules/workbench';
import {
WorkbenchLink,
WorkbenchService,
} from '@affine/core/modules/workbench';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import type { DocCollection, DocMeta } from '@blocksuite/store';
import { useDraggable } from '@dnd-kit/core';
import * as Collapsible from '@radix-ui/react-collapsible';
import { DocsService, useLiveData, useService } from '@toeverything/infra';
import React, { useCallback, useMemo } from 'react';
import React, { useMemo } from 'react';
import {
type DNDIdentifier,
getDNDId,
} from '../../../../hooks/affine/use-global-dnd-helper';
import { useNavigateHelper } from '../../../../hooks/use-navigate-helper';
import { MenuItem as CollectionItem } from '../../../app-sidebar';
import { MenuLinkItem } from '../../../app-sidebar';
import { DragMenuItemOverlay } from '../components/drag-menu-item-overlay';
import { PostfixItem } from '../components/postfix-item';
import { ReferencePage } from '../components/reference-page';
@@ -50,11 +52,6 @@ export const Doc = ({
return docMode === 'edgeless' ? <EdgelessIcon /> : <PageIcon />;
}, [docMode]);
const { jumpToPage } = useNavigateHelper();
const clickDoc = useCallback(() => {
jumpToPage(docCollection.id, doc.id);
}, [jumpToPage, doc.id, docCollection.id]);
const references = useBlockSuitePageReferences(docCollection, docId);
const referencesToRender = references.filter(
id => allPageMeta[id] && !allPageMeta[id]?.trash
@@ -78,11 +75,12 @@ export const Doc = ({
data-draggable={true}
data-dragging={isDragging}
>
<CollectionItem
<MenuLinkItem
data-testid="collection-page"
data-type="collection-list-item"
icon={icon}
onClick={clickDoc}
to={`/${docId}`}
linkComponent={WorkbenchLink}
className={styles.title}
active={active}
collapsed={referencesToRender.length > 0 ? collapsed : undefined}
@@ -101,7 +99,7 @@ export const Doc = ({
{...listeners}
>
{doc.title || t['Untitled']()}
</CollectionItem>
</MenuLinkItem>
<Collapsible.Content className={styles.collapsibleContent}>
{referencesToRender.map(id => {
return (
@@ -150,3 +150,9 @@ export const emptyCollectionNewButton = style({
height: '28px',
fontSize: cssVar('fontXs'),
});
export const docsListContainer = style({
marginLeft: 20,
display: 'flex',
flexDirection: 'column',
gap: 4,
});
@@ -1,5 +1,8 @@
import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references';
import { WorkbenchService } from '@affine/core/modules/workbench';
import {
WorkbenchLink,
WorkbenchService,
} from '@affine/core/modules/workbench';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import type { DocCollection, DocMeta } from '@blocksuite/store';
@@ -60,10 +63,11 @@ export const ReferencePage = ({
data-type="reference-page"
data-testid={`reference-page-${pageId}`}
active={active}
to={`/workspace/${docCollection.id}/${pageId}`}
to={`/${pageId}`}
icon={icon}
collapsed={collapsible ? collapsed : undefined}
onCollapsedChange={setCollapsed}
linkComponent={WorkbenchLink}
postfix={
<PostfixItem
docCollection={docCollection}
@@ -3,7 +3,10 @@ import {
parseDNDId,
} from '@affine/core/hooks/affine/use-global-dnd-helper';
import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references';
import { WorkbenchService } from '@affine/core/modules/workbench';
import {
WorkbenchLink,
WorkbenchService,
} from '@affine/core/modules/workbench';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import { type AnimateLayoutChanges, useSortable } from '@dnd-kit/sortable';
@@ -102,7 +105,8 @@ export const FavouriteDocSidebarNavItem = ({
data-dragging={isDragging}
className={draggableMenuItemStyles.draggableMenuItem}
active={linkActive}
to={`/workspace/${workspace.id}/${pageId}`}
to={`/${pageId}`}
linkComponent={WorkbenchLink}
collapsed={collapsible ? collapsed : undefined}
onCollapsedChange={setCollapsed}
postfix={