fix(core): ai chat bugs (#7283)

Closes: [AF-929](https://linear.app/affine-design/issue/AF-929/continue-with-ai-点击后应当是立即激活选区)

* [x] remove icon background on `chat-input`
* [x] activate the selected card immediately
* [x] fix quote when selecting `Start with this doc`
* [x] clear candidate card list when switching doc

https://github.com/toeverything/AFFiNE/assets/27926/706d499e-b738-4bb4-9353-510f73613875
This commit is contained in:
fundon 2024-06-20 11:57:36 +00:00
parent b99e8b1e8a
commit dbd678cc31
No known key found for this signature in database
GPG Key ID: 398BFA91AC539CF7
2 changed files with 91 additions and 20 deletions

View File

@ -6,7 +6,14 @@ import {
NoteDisplayMode, NoteDisplayMode,
} from '@blocksuite/blocks'; } from '@blocksuite/blocks';
import type { BlockModel } from '@blocksuite/store'; import type { BlockModel } from '@blocksuite/store';
import { css, html, LitElement, nothing, type PropertyValues } from 'lit'; import {
css,
html,
LitElement,
nothing,
type PropertyValues,
type TemplateResult,
} from 'lit';
import { customElement, property, state } from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js'; import { repeat } from 'lit/directives/repeat.js';
import { styleMap } from 'lit/directives/style-map.js'; import { styleMap } from 'lit/directives/style-map.js';
@ -107,6 +114,7 @@ export class ChatCards extends WithDisposable(LitElement) {
@state() @state()
accessor cards: Card[] = []; accessor cards: Card[] = [];
private _currentDocId: string | null = null;
private _selectedCardId: number = 0; private _selectedCardId: number = 0;
static renderText({ text }: CardText) { static renderText({ text }: CardText) {
@ -153,6 +161,7 @@ export class ChatCards extends WithDisposable(LitElement) {
style=${styleMap({ style=${styleMap({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
maxWidth: 'calc(100% - 72px)',
})} })}
> >
<div class="card-title"> <div class="card-title">
@ -172,14 +181,66 @@ export class ChatCards extends WithDisposable(LitElement) {
`; `;
} }
static renderDoc(_: CardBlock) { static renderDoc({ text, images }: CardBlock) {
let textTpl = html`you've chosen within the doc`;
let imageTpl: TemplateResult<1> | typeof nothing = nothing;
let hasImage = false;
if (text?.length) {
const lines = text.split('\n');
textTpl = html`${repeat(
lines.slice(0, 2),
line => line,
line => html`
<div
style=${styleMap({
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
})}
>
${line}
</div>
`
)}`;
}
if (images?.length) {
hasImage = true;
imageTpl = html`
<img
style=${styleMap({
maxWidth: '72px',
maxHeight: '46px',
})}
src="${URL.createObjectURL(images[0])}"
/>
`;
}
return html` return html`
<div class="card-wrapper"> <div
<div class="card-title"> class="card-wrapper"
${DocIcon} style=${styleMap({
<div>Start with this doc</div> display: 'flex',
gap: '8px',
justifyContent: 'space-between',
})}
>
<div
style=${styleMap({
display: 'flex',
flexDirection: 'column',
maxWidth: hasImage ? 'calc(100% - 72px)' : '100%',
})}
>
<div class="card-title">
${DocIcon}
<div>Start with this doc</div>
</div>
<div class="second-text">${textTpl}</div>
</div> </div>
<div class="second-text">you've chosen within the doc</div> ${imageTpl}
</div> </div>
`; `;
} }
@ -218,7 +279,7 @@ export class ChatCards extends WithDisposable(LitElement) {
card.images = images; card.images = images;
} }
private async _handleClick(card: Card) { private async _selectCard(card: Card) {
AIProvider.slots.toggleChatCards.emit({ visible: false }); AIProvider.slots.toggleChatCards.emit({ visible: false });
this._selectedCardId = card.id; this._selectedCardId = card.id;
@ -361,19 +422,27 @@ export class ChatCards extends WithDisposable(LitElement) {
protected override async updated(changedProperties: PropertyValues) { protected override async updated(changedProperties: PropertyValues) {
if (changedProperties.has('host')) { if (changedProperties.has('host')) {
if (this._currentDocId === this.host.doc.id) return;
this._currentDocId = this.host.doc.id;
this.cards = [];
const { text, images } = await this._extractAll(); const { text, images } = await this._extractAll();
const hasText = text.length > 0; const hasText = text.length > 0;
const hasImages = images.length > 0; const hasImages = images.length > 0;
// Currently only supports checking on first load // Currently only supports checking on first load
if ( if (hasText || hasImages) {
(hasText || hasImages) && const card: CardBlock = {
!this.cards.some(card => card.type === CardType.Doc)
) {
this._updateCards({
id: Date.now(), id: Date.now(),
type: CardType.Doc, type: CardType.Doc,
}); };
if (hasText) {
card.text = text;
}
if (hasImages) {
card.images = images;
}
this._updateCards(card);
} }
} }
} }
@ -388,6 +457,13 @@ export class ChatCards extends WithDisposable(LitElement) {
} else { } else {
await this._extract(); await this._extract();
} }
if (this.cards.length > 0) {
const card = this.cards[0];
if (card.type === CardType.Doc) return;
await this._selectCard(card);
}
}) })
); );
@ -408,7 +484,7 @@ export class ChatCards extends WithDisposable(LitElement) {
this.cards, this.cards,
card => card.id, card => card.id,
card => html` card => html`
<div @click=${() => this._handleClick(card)}> <div @click=${() => this._selectCard(card)}>
${this._renderCard(card)} ${this._renderCard(card)}
</div> </div>
` `

View File

@ -106,12 +106,7 @@ export class ChatPanelInput extends WithDisposable(LitElement) {
margin-left: auto; margin-left: auto;
} }
.chat-history-clear {
background-color: var(--affine-white);
}
.image-upload { .image-upload {
background-color: var(--affine-white);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;