refactor: move doc-title and ai-chat-block components (#10316)

### TL;DR
Moved doc title and AI chat block components to more appropriate locations while removing unused backlink functionality.

### What changed?
- Relocated doc title component from presets to affine-components
- Moved AI chat block from presets/blocks to blocks directory
- Removed unused backlink-related code and components
- Updated imports across files to reference new component locations
- Consolidated AI-related exports through a single entry point

### How to test?
1. Verify doc title still renders correctly in documents
2. Confirm AI chat functionality works as expected
3. Check that no backlink-related features are accessible
4. Ensure all AI features continue to work through the new import paths

### Why make this change?
This reorganization improves code organization by:
- Placing components closer to their related functionality
- Removing dead/unused code around backlinks
- Simplifying the import structure for AI-related features
- Making the codebase more maintainable by consolidating related components
This commit is contained in:
Saul-Mirone
2025-02-20 10:45:47 +00:00
parent 4f831732e1
commit 1516903c77
49 changed files with 66 additions and 280 deletions

View File

@@ -22,6 +22,7 @@ import { effects as componentCaptionEffects } from '@blocksuite/affine-component
import { effects as componentColorPickerEffects } from '@blocksuite/affine-components/color-picker';
import { effects as componentContextMenuEffects } from '@blocksuite/affine-components/context-menu';
import { effects as componentDatePickerEffects } from '@blocksuite/affine-components/date-picker';
import { effects as componentDocTitleEffects } from '@blocksuite/affine-components/doc-title';
import { effects as componentDropIndicatorEffects } from '@blocksuite/affine-components/drop-indicator';
import { effects as componentEmbedCardModalEffects } from '@blocksuite/affine-components/embed-card-modal';
import { FilterableListComponent } from '@blocksuite/affine-components/filterable-list';
@@ -213,6 +214,7 @@ export function effects() {
componentAiItemEffects();
componentColorPickerEffects();
componentEmbedCardModalEffects();
componentDocTitleEffects();
widgetScrollAnchoringEffects();
widgetMobileToolbarEffects();

View File

@@ -58,6 +58,10 @@ export {
type MenuOptions,
onMenuOpen,
} from '@blocksuite/affine-components/context-menu';
export {
DocTitle,
getDocTitleByEditorHost,
} from '@blocksuite/affine-components/doc-title';
export {
HoverController,
whenHover,

View File

@@ -7,8 +7,6 @@ import {
PageEditor,
} from './editors/index.js';
import { CommentInput } from './fragments/comment/comment-input.js';
import { BacklinkButton } from './fragments/doc-meta-tags/backlink-popover.js';
import { effects as docTitleEffects } from './fragments/doc-title/index.js';
import {
AFFINE_FRAME_PANEL_BODY,
FramePanelBody,
@@ -70,8 +68,6 @@ import {
} from './fragments/outline/header/outline-setting-menu.js';
export function effects() {
docTitleEffects();
customElements.define('page-editor', PageEditor);
customElements.define('comment-input', CommentInput);
customElements.define(
@@ -82,7 +78,6 @@ export function effects() {
customElements.define(AFFINE_OUTLINE_NOTICE, OutlineNotice);
customElements.define('comment-panel', CommentPanel);
customElements.define(AFFINE_OUTLINE_PANEL, OutlinePanel);
customElements.define('backlink-button', BacklinkButton);
customElements.define(AFFINE_OUTLINE_PANEL_HEADER, OutlinePanelHeader);
customElements.define('affine-editor-container', AffineEditorContainer);
customElements.define(AFFINE_OUTLINE_NOTE_CARD, OutlineNoteCard);

View File

@@ -1,148 +0,0 @@
import { DualLinkIcon16, scrollbarStyle } from '@blocksuite/blocks';
import { WithDisposable } from '@blocksuite/global/utils';
import { baseTheme } from '@toeverything/theme';
import { css, html, LitElement, unsafeCSS } from 'lit';
import { state } from 'lit/decorators.js';
import { type BacklinkData, DEFAULT_DOC_NAME } from './utils.js';
export class BacklinkButton extends WithDisposable(LitElement) {
static override styles = css`
:host {
position: relative;
display: flex;
}
.btn {
padding: 0 12px;
box-sizing: border-box;
display: inline-flex;
align-items: center;
border: none;
height: 30px;
border-radius: 8px;
gap: 4px;
background: transparent;
cursor: pointer;
user-select: none;
font-size: var(--affine-font-sm);
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
fill: var(--affine-text-secondary-color);
color: var(--affine-text-secondary-color);
pointer-events: auto;
}
.btn > span {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.btn:hover {
background: var(--affine-hover-color);
}
.btn:active {
background: var(--affine-hover-color);
}
.backlink-popover {
position: absolute;
left: 0;
bottom: 0;
transform: translateY(100%);
z-index: 1;
padding-top: 8px;
}
.menu {
display: flex;
flex-direction: column;
padding: 8px 4px;
background: var(--affine-white);
box-shadow: var(--affine-menu-shadow);
border-radius: 12px;
}
.backlink-popover .group-title {
color: var(--affine-text-secondary-color);
margin: 8px 12px;
}
.backlink-popover icon-button {
padding: 8px;
justify-content: flex-start;
gap: 8px;
}
${scrollbarStyle('.backlink-popover .group')}
`;
private readonly _backlinks: BacklinkData[];
// Handle click outside
private readonly _onClickAway = (e: Event) => {
if (e.target === this) return;
if (!this._showPopover) return;
this._showPopover = false;
document.removeEventListener('mousedown', this._onClickAway);
};
constructor(backlinks: BacklinkData[]) {
super();
this._backlinks = backlinks;
}
override connectedCallback() {
super.connectedCallback();
this.tabIndex = 0;
}
onClick() {
this._showPopover = !this._showPopover;
document.addEventListener('mousedown', this._onClickAway);
}
override render() {
// Only show linked doc backlinks
const backlinks = this._backlinks;
if (!backlinks.length) return null;
return html`
<div class="btn" @click="${this.onClick}">
${DualLinkIcon16}<span>Backlinks (${backlinks.length})</span>
${this._showPopover ? backlinkPopover(backlinks) : null}
</div>
`;
}
@state()
private accessor _showPopover = false;
}
function backlinkPopover(backlinks: BacklinkData[]) {
return html`<div
class="backlink-popover"
@click=${(e: MouseEvent) => e.stopPropagation()}
>
<div class="menu">
<div class="group-title">Linked to this doc</div>
<div class="group" style="overflow-y: scroll; max-height: 372px;">
${backlinks.map(link => {
const title = link.title || DEFAULT_DOC_NAME;
return html`<icon-button
width="248px"
height="32px"
text="${title}"
@mousedown="${link.jump}"
>
${link.icon}
</icon-button>`;
})}
</div>
</div>
</div>`;
}

View File

@@ -1,19 +0,0 @@
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import type { DocMeta } from '@blocksuite/store';
import type { TemplateResult } from 'lit';
export const DOC_BLOCK_CHILD_PADDING = 24;
export const DEFAULT_DOC_NAME = 'Untitled';
export type BackLink = {
pageId: string;
blockId: string;
type: NonNullable<AffineTextAttributes['reference']>['type'];
};
export type BacklinkData = BackLink &
DocMeta & {
jump: () => void;
icon: TemplateResult;
};

View File

@@ -1 +0,0 @@
export * from '@blocksuite/affine-components/doc-title';

View File

@@ -1,4 +1,3 @@
export * from './comment/index.js';
export * from './doc-title/index.js';
export * from './frame-panel/index.js';
export * from './outline/index.js';

View File

@@ -1,9 +1,8 @@
import type { EditorHost } from '@blocksuite/block-std';
import { NoteDisplayMode } from '@blocksuite/blocks';
import { getDocTitleByEditorHost, NoteDisplayMode } from '@blocksuite/blocks';
import { clamp, DisposableGroup } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '../../../editors/editor-container.js';
import { getDocTitleByEditorHost } from '../../doc-title/index.js';
import { getHeadingBlocksFromDoc } from './query.js';
export function scrollToBlock(editor: AffineEditorContainer, blockId: string) {