mirror of
https://github.com/toeverything/AFFiNE.git
synced 2025-01-07 05:16:30 +03:00
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:
parent
b99e8b1e8a
commit
dbd678cc31
@ -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>
|
||||||
`
|
`
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user