mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-20 03:26:47 +08:00
feat(core): impl doc display meta extension (#9165)
Closes: [BS-2111](https://linear.app/affine-design/issue/BS-2111/定义和实现-docdisplaymetaextension) Upstreams: https://github.com/toeverything/blocksuite/pull/8953 https://github.com/user-attachments/assets/008d7433-efef-47c4-8189-9bc288e61199
This commit is contained in:
@@ -3,7 +3,6 @@ import { JournalService } from '@affine/core/modules/journal';
|
||||
import { PeekViewService } from '@affine/core/modules/peek-view/services/peek-view';
|
||||
import { useInsidePeekView } from '@affine/core/modules/peek-view/view/modal-container';
|
||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/affine/blocks';
|
||||
import type { DocCollection } from '@blocksuite/affine/store';
|
||||
@@ -30,7 +29,7 @@ import * as styles from './styles.css';
|
||||
interface AffinePageReferenceProps {
|
||||
pageId: string;
|
||||
params?: URLSearchParams;
|
||||
title?: string | null; // title alias
|
||||
title?: string; // title alias
|
||||
className?: string;
|
||||
Icon?: ComponentType;
|
||||
onClick?: (e: MouseEvent) => void;
|
||||
@@ -44,7 +43,6 @@ function AffinePageReferenceInner({
|
||||
}: AffinePageReferenceProps) {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const docsService = useService(DocsService);
|
||||
const i18n = useI18n();
|
||||
|
||||
let referenceWithMode: DocMode | null = null;
|
||||
let referenceToNode = false;
|
||||
@@ -74,18 +72,10 @@ function AffinePageReferenceInner({
|
||||
|
||||
const notFound = !useLiveData(docsService.list.doc$(pageId));
|
||||
|
||||
const docTitle = useLiveData(
|
||||
docDisplayMetaService.title$(pageId, { reference: true })
|
||||
title = useLiveData(
|
||||
docDisplayMetaService.title$(pageId, { title, reference: true })
|
||||
);
|
||||
|
||||
if (notFound) {
|
||||
title = i18n.t('com.affine.notFoundPage.title');
|
||||
}
|
||||
|
||||
if (!title) {
|
||||
title = i18n.t(docTitle);
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={notFound ? styles.notFound : ''}>
|
||||
<Icon className={styles.pageReferenceIcon} />
|
||||
|
||||
+91
@@ -2,6 +2,7 @@ import {
|
||||
AIEdgelessRootBlockSpec,
|
||||
AIPageRootBlockSpec,
|
||||
} from '@affine/core/blocksuite/presets/ai';
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||
import { AppThemeService } from '@affine/core/modules/theme';
|
||||
import { mixpanel } from '@affine/track';
|
||||
@@ -12,12 +13,15 @@ import {
|
||||
StdIdentifier,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import type {
|
||||
DocDisplayMetaExtension,
|
||||
DocDisplayMetaParams,
|
||||
RootBlockConfig,
|
||||
TelemetryEventMap,
|
||||
ThemeExtension,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import {
|
||||
ColorScheme,
|
||||
DocDisplayMetaProvider,
|
||||
EdgelessBuiltInManager,
|
||||
EdgelessRootBlockSpec,
|
||||
EdgelessToolExtension,
|
||||
@@ -29,16 +33,19 @@ import {
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import {
|
||||
createSignalFromObservable,
|
||||
referenceToNode,
|
||||
type Signal,
|
||||
SpecProvider,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import type { Container } from '@blocksuite/global/di';
|
||||
import { LinkedPageIcon, PageIcon } from '@blocksuite/icons/lit';
|
||||
import {
|
||||
DocService,
|
||||
DocsService,
|
||||
FeatureFlagService,
|
||||
type FrameworkProvider,
|
||||
} from '@toeverything/infra';
|
||||
import type { TemplateResult } from 'lit';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { combineLatest, map } from 'rxjs';
|
||||
|
||||
@@ -141,6 +148,88 @@ function getThemeExtension(framework: FrameworkProvider) {
|
||||
return AffineThemeExtension;
|
||||
}
|
||||
|
||||
export function buildDocDisplayMetaExtension(framework: FrameworkProvider) {
|
||||
const docDisplayMetaService = framework.get(DocDisplayMetaService);
|
||||
|
||||
function iconBuilder(
|
||||
icon: typeof PageIcon,
|
||||
size = '1.25em',
|
||||
style = 'user-select:none;flex-shrink:0;vertical-align:middle;font-size:inherit;margin-bottom:0.1em;'
|
||||
) {
|
||||
return icon({
|
||||
width: size,
|
||||
height: size,
|
||||
style,
|
||||
});
|
||||
}
|
||||
|
||||
class AffineDocDisplayMetaService
|
||||
extends LifeCycleWatcher
|
||||
implements DocDisplayMetaExtension
|
||||
{
|
||||
static override key = 'doc-display-meta';
|
||||
|
||||
readonly disposables: (() => void)[] = [];
|
||||
|
||||
static override setup(di: Container) {
|
||||
super.setup(di);
|
||||
di.override(DocDisplayMetaProvider, this, [StdIdentifier]);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
while (this.disposables.length > 0) {
|
||||
this.disposables.pop()?.();
|
||||
}
|
||||
}
|
||||
|
||||
icon(
|
||||
docId: string,
|
||||
{ params, title, referenced }: DocDisplayMetaParams = {}
|
||||
): Signal<TemplateResult> {
|
||||
const icon$ = docDisplayMetaService
|
||||
.icon$(docId, {
|
||||
type: 'lit',
|
||||
reference: referenced,
|
||||
hasTitleAlias: Boolean(title),
|
||||
referenceToNode: referenceToNode({ pageId: docId, params }),
|
||||
})
|
||||
.map(iconBuilder);
|
||||
|
||||
const { signal: iconSignal, cleanup } = createSignalFromObservable(
|
||||
icon$,
|
||||
iconBuilder(referenced ? LinkedPageIcon : PageIcon)
|
||||
);
|
||||
|
||||
this.disposables.push(cleanup);
|
||||
|
||||
return iconSignal;
|
||||
}
|
||||
|
||||
title(
|
||||
docId: string,
|
||||
{ title = '', referenced }: DocDisplayMetaParams = {}
|
||||
): Signal<string> {
|
||||
const title$ = docDisplayMetaService.title$(docId, {
|
||||
title,
|
||||
reference: referenced,
|
||||
});
|
||||
|
||||
const { signal: titleSignal, cleanup } =
|
||||
createSignalFromObservable<string>(title$, title);
|
||||
|
||||
this.disposables.push(cleanup);
|
||||
|
||||
return titleSignal;
|
||||
}
|
||||
|
||||
override unmounted() {
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return AffineDocDisplayMetaService;
|
||||
}
|
||||
|
||||
function getEditorConfigExtension(
|
||||
framework: FrameworkProvider
|
||||
): ExtensionType[] {
|
||||
@@ -184,6 +273,7 @@ export function createPageRootBlockSpec(
|
||||
getFontConfigExtension(),
|
||||
getTelemetryExtension(),
|
||||
getEditorConfigExtension(framework),
|
||||
buildDocDisplayMetaExtension(framework),
|
||||
].flat();
|
||||
}
|
||||
|
||||
@@ -201,5 +291,6 @@ export function createEdgelessRootBlockSpec(
|
||||
getFontConfigExtension(),
|
||||
getTelemetryExtension(),
|
||||
getEditorConfigExtension(framework),
|
||||
buildDocDisplayMetaExtension(framework),
|
||||
].flat();
|
||||
}
|
||||
|
||||
-1
@@ -312,7 +312,6 @@ export function patchDocModeService(
|
||||
return (mode || DEFAULT_MODE) as DocMode;
|
||||
};
|
||||
onPrimaryModeChange = (handler: (mode: DocMode) => void, id?: string) => {
|
||||
// eslint-disable-next-line rxjs/finnish
|
||||
const mode$ = id
|
||||
? docsService.list.primaryMode$(id)
|
||||
: docService.doc.primaryMode$;
|
||||
|
||||
Reference in New Issue
Block a user