From a6692f70aa012ea6b6906930552da16ad74c0438 Mon Sep 17 00:00:00 2001 From: akumatus Date: Tue, 4 Mar 2025 15:25:35 +0000 Subject: [PATCH] fix(core): text style is not centered when chat-panel is wide (#10607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix issue [BS-2751](https://linear.app/affine-design/issue/BS-2751). Before: ![截屏2025-03-04 16.56.46.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/d0aae342-ff53-42d6-964b-ecd2e8720af6.png) After: ![截屏2025-03-04 16.56.57.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/986bde63-6fe8-485d-97d1-0a062658cf7c.png) --- .../ai/chat-panel/chat-panel-messages.ts | 118 ++++++++++-------- .../src/blocksuite/ai/chat-panel/index.ts | 6 +- .../blocksuite/ai/components/text-renderer.ts | 5 + .../affine-cloud-copilot/e2e/copilot.spec.ts | 2 +- 4 files changed, 77 insertions(+), 54 deletions(-) diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts index c54872b038..0290317ee9 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts @@ -11,7 +11,6 @@ import type { BaseSelection } from '@blocksuite/affine/store'; import { css, html, nothing } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; -import { styleMap } from 'lit/directives/style-map.js'; import { debounce } from 'lodash-es'; import { @@ -50,7 +49,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { overflow-y: auto; } - .chat-panel-messages-placeholder { + .messages-placeholder { width: 100%; position: absolute; z-index: 1; @@ -63,6 +62,47 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { gap: 12px; } + .messages-placeholder-title { + font-size: 18px; + font-weight: 600; + color: var(--affine-text-primary-color); + } + + .messages-placeholder-title[data-loading='true'] { + font-size: var(--affine-font-sm); + color: var(--affine-text-secondary-color); + } + + .onboarding-wrapper { + display: flex; + gap: 8px; + flex-direction: column; + margin-top: 16px; + } + + .onboarding-item { + display: flex; + height: 28px; + gap: 8px; + align-items: center; + justify-content: start; + cursor: pointer; + } + + .onboarding-item-icon { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + .onboarding-item-text { + font-size: var(--affine-font-xs); + font-weight: 400; + color: var(--affine-text-primary-color); + white-space: nowrap; + } + .item-wrapper { margin-left: 32px; } @@ -73,14 +113,14 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { gap: 10px; margin-bottom: 4px; color: var(--affine-text-primary-color); - font-size: 14px; + font-size: var(--affine-font-sm); font-weight: 500; user-select: none; } .message-info { color: var(--affine-placeholder-color); - font-size: 12px; + font-size: var(--affine-font-xs); font-weight: 400; } @@ -126,7 +166,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { accessor _selectionValue: BaseSelection[] = []; @state() - accessor showDownIndicator = false; + accessor canScrollDown = false; @state() accessor avatarUrl = ''; @@ -156,46 +196,32 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { return this.messagesContainer; } + get showDownIndicator() { + if (!this.messagesContainer) return false; + const { clientHeight, scrollTop, scrollHeight } = this.messagesContainer; + const canScrollDown = scrollHeight - scrollTop - clientHeight > 200; + const showDownIndicator = + canScrollDown && + this.chatContextValue.items.length > 0 && + this.chatContextValue.status !== 'transmitting'; + return showDownIndicator; + } + private _renderAIOnboarding() { return this.isLoading || !this.host?.doc.get(FeatureFlagService).getFlag('enable_ai_onboarding') ? nothing - : html`
+ : html`
${repeat( AIPreloadConfig, config => config.text, config => { return html`
config.handler()} - style=${styleMap({ - display: 'flex', - height: '28px', - gap: '8px', - width: '88%', - alignItems: 'center', - justifyContent: 'start', - cursor: 'pointer', - })} + class="onboarding-item" > - ${config.icon} -
- ${config.text} -
+
${config.icon}
+
${config.text}
`; } )} @@ -205,7 +231,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { private readonly _onScroll = () => { if (!this.messagesContainer) return; const { clientHeight, scrollTop, scrollHeight } = this.messagesContainer; - this.showDownIndicator = scrollHeight - scrollTop - clientHeight > 200; + this.canScrollDown = scrollHeight - scrollTop - clientHeight > 200; }; private readonly _debouncedOnScroll = debounce( @@ -225,28 +251,19 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { ); }); - return html` - + return html`
this._debouncedOnScroll()} > - ${items.length === 0 - ? html`
+ ${filteredItems.length === 0 + ? html`
${AffineIcon( isLoading ? 'var(--affine-icon-secondary)' : 'var(--affine-primary-color)' )} -
+
${this.isLoading ? 'AFFiNE AI is loading history...' : 'What can I help you with?'} @@ -267,11 +284,12 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { } )}
- ${this.showDownIndicator && filteredItems.length > 1 + ${this.showDownIndicator && filteredItems.length > 0 ? html`
${DownArrowIcon}
` - : nothing} `; + : nothing} + `; } override connectedCallback() { diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts index 30ff53539c..3c67488854 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -133,7 +133,6 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) { private readonly _updateHistory = async () => { const { doc } = this; - this.isLoading = true; const currentRequest = ++this._updateHistoryCounter; @@ -164,7 +163,6 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) { ), }; - this.isLoading = false; this._scrollToEnd(); }; @@ -253,7 +251,7 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) { accessor previewSpecBuilder!: SpecBuilder; @state() - accessor isLoading = false; + accessor isLoading = true; @state() accessor chatContextValue: ChatContextValue = DEFAULT_CHAT_CONTEXT_VALUE; @@ -301,6 +299,7 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) { const userId = (await AIProvider.userInfo)?.id; if (!userId) return; + this.isLoading = true; const sessions = await AIProvider.session?.getSessions( this.doc.workspace.id, this.doc.id @@ -309,6 +308,7 @@ export class ChatPanel extends WithDisposable(ShadowlessElement) { this._chatSessionId = sessions?.[0].id; await this._updateHistory(); } + this.isLoading = false; if (this._chatSessionId) { this._chatContextId = await AIProvider.context?.getContextId( this.doc.workspace.id, diff --git a/packages/frontend/core/src/blocksuite/ai/components/text-renderer.ts b/packages/frontend/core/src/blocksuite/ai/components/text-renderer.ts index ddbc5e4831..f25995803c 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/text-renderer.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/text-renderer.ts @@ -313,6 +313,11 @@ export class TextRenderer extends WithDisposable(ShadowlessElement) { ); // Apply min-height to prevent shrinking this._container.style.minHeight = `${this._maxContainerHeight}px`; + } else { + setTimeout(() => { + this._maxContainerHeight = 0; + this._container.style.minHeight = ''; + }, 500); } }); } diff --git a/tests/affine-cloud-copilot/e2e/copilot.spec.ts b/tests/affine-cloud-copilot/e2e/copilot.spec.ts index 51cfffde9a..60e0835193 100644 --- a/tests/affine-cloud-copilot/e2e/copilot.spec.ts +++ b/tests/affine-cloud-copilot/e2e/copilot.spec.ts @@ -106,7 +106,7 @@ const clearChat = async (page: Page) => { const collectChat = async (page: Page) => { await page.waitForTimeout(ONE_SECOND); const chatPanel = await page.waitForSelector('.chat-panel-messages'); - if (await chatPanel.$('.chat-panel-messages-placeholder')) { + if (await chatPanel.$('.messages-placeholder')) { return []; } // wait ai response