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,
} from '@blocksuite/blocks';
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 { repeat } from 'lit/directives/repeat.js';
import { styleMap } from 'lit/directives/style-map.js';
@ -107,6 +114,7 @@ export class ChatCards extends WithDisposable(LitElement) {
@state()
accessor cards: Card[] = [];
private _currentDocId: string | null = null;
private _selectedCardId: number = 0;
static renderText({ text }: CardText) {
@ -153,6 +161,7 @@ export class ChatCards extends WithDisposable(LitElement) {
style=${styleMap({
display: 'flex',
flexDirection: 'column',
maxWidth: 'calc(100% - 72px)',
})}
>
<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`
<div class="card-wrapper">
<div class="card-title">
${DocIcon}
<div>Start with this doc</div>
<div
class="card-wrapper"
style=${styleMap({
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 class="second-text">you've chosen within the doc</div>
${imageTpl}
</div>
`;
}
@ -218,7 +279,7 @@ export class ChatCards extends WithDisposable(LitElement) {
card.images = images;
}
private async _handleClick(card: Card) {
private async _selectCard(card: Card) {
AIProvider.slots.toggleChatCards.emit({ visible: false });
this._selectedCardId = card.id;
@ -361,19 +422,27 @@ export class ChatCards extends WithDisposable(LitElement) {
protected override async updated(changedProperties: PropertyValues) {
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 hasText = text.length > 0;
const hasImages = images.length > 0;
// Currently only supports checking on first load
if (
(hasText || hasImages) &&
!this.cards.some(card => card.type === CardType.Doc)
) {
this._updateCards({
if (hasText || hasImages) {
const card: CardBlock = {
id: Date.now(),
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 {
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,
card => card.id,
card => html`
<div @click=${() => this._handleClick(card)}>
<div @click=${() => this._selectCard(card)}>
${this._renderCard(card)}
</div>
`

View File

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