feat(core): add ai history loading placeholder (#13092)
Close [AI-324](https://linear.app/affine-design/issue/AI-324) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a loading state indicator to the chat panel, displaying a styled message and icon while history is loading. * Enhanced the session history component with clear loading and empty state messages for improved user feedback. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -18,6 +18,7 @@ import { css, html, nothing, type PropertyValues } from 'lit';
|
|||||||
import { property, state } from 'lit/decorators.js';
|
import { property, state } from 'lit/decorators.js';
|
||||||
import { keyed } from 'lit/directives/keyed.js';
|
import { keyed } from 'lit/directives/keyed.js';
|
||||||
|
|
||||||
|
import { AffineIcon } from '../_common/icons';
|
||||||
import type {
|
import type {
|
||||||
DocDisplayConfig,
|
DocDisplayConfig,
|
||||||
SearchMenuConfig,
|
SearchMenuConfig,
|
||||||
@@ -50,6 +51,28 @@ export class ChatPanel extends SignalWatcher(
|
|||||||
color: var(--affine-text-secondary-color);
|
color: var(--affine-text-secondary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-loading-container {
|
||||||
|
position: relative;
|
||||||
|
padding: 44px 0 166px 0;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-loading {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-loading-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--affine-font-sm);
|
||||||
|
color: var(--affine-text-secondary-color);
|
||||||
|
}
|
||||||
|
|
||||||
.chat-panel-playground {
|
.chat-panel-playground {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
@@ -394,7 +417,14 @@ export class ChatPanel extends SignalWatcher(
|
|||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
if (!this.isInitialized) {
|
if (!this.isInitialized) {
|
||||||
return nothing;
|
return html`<div class="chat-loading-container">
|
||||||
|
<div class="chat-loading">
|
||||||
|
${AffineIcon('var(--affine-icon-secondary)')}
|
||||||
|
<div class="chat-loading-title">
|
||||||
|
<span> AFFiNE AI is loading history... </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`<div class="chat-panel-container">
|
return html`<div class="chat-panel-container">
|
||||||
|
|||||||
@@ -30,6 +30,21 @@ export class AISessionHistory extends WithDisposable(ShadowlessElement) {
|
|||||||
background: ${unsafeCSSVarV2('layer/background/overlayPanel')};
|
background: ${unsafeCSSVarV2('layer/background/overlayPanel')};
|
||||||
box-shadow: ${unsafeCSSVar('overlayPanelShadow')};
|
box-shadow: ${unsafeCSSVar('overlayPanelShadow')};
|
||||||
|
|
||||||
|
.loading-container,
|
||||||
|
.empty-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 344px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-title,
|
||||||
|
.empty-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--affine-font-sm);
|
||||||
|
color: var(--affine-text-secondary-color);
|
||||||
|
}
|
||||||
|
|
||||||
.ai-session-group {
|
.ai-session-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -125,6 +140,9 @@ export class AISessionHistory extends WithDisposable(ShadowlessElement) {
|
|||||||
@state()
|
@state()
|
||||||
private accessor sessions: BlockSuitePresets.AIRecentSession[] = [];
|
private accessor sessions: BlockSuitePresets.AIRecentSession[] = [];
|
||||||
|
|
||||||
|
@state()
|
||||||
|
private accessor loading = true;
|
||||||
|
|
||||||
private groupSessionsByTime(
|
private groupSessionsByTime(
|
||||||
sessions: BlockSuitePresets.AIRecentSession[]
|
sessions: BlockSuitePresets.AIRecentSession[]
|
||||||
): GroupedSessions {
|
): GroupedSessions {
|
||||||
@@ -174,6 +192,7 @@ export class AISessionHistory extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getRecentSessions() {
|
private async getRecentSessions() {
|
||||||
|
this.loading = true;
|
||||||
const limit = 50;
|
const limit = 50;
|
||||||
const sessions = await AIProvider.session?.getRecentSessions(
|
const sessions = await AIProvider.session?.getRecentSessions(
|
||||||
this.workspaceId,
|
this.workspaceId,
|
||||||
@@ -182,6 +201,7 @@ export class AISessionHistory extends WithDisposable(ShadowlessElement) {
|
|||||||
if (sessions) {
|
if (sessions) {
|
||||||
this.sessions = sessions;
|
this.sessions = sessions;
|
||||||
}
|
}
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
override connectedCallback() {
|
override connectedCallback() {
|
||||||
@@ -241,11 +261,27 @@ export class AISessionHistory extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
if (this.sessions.length === 0) {
|
if (this.loading) {
|
||||||
return nothing;
|
return html`
|
||||||
|
<div class="ai-session-history">
|
||||||
|
<div class="loading-container">
|
||||||
|
<div class="loading-title">Loading history...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
const groupedSessions = this.groupSessionsByTime(this.sessions);
|
|
||||||
|
|
||||||
|
if (this.sessions.length === 0) {
|
||||||
|
return html`
|
||||||
|
<div class="ai-session-history">
|
||||||
|
<div class="empty-container">
|
||||||
|
<div class="empty-title">Empty history</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupedSessions = this.groupSessionsByTime(this.sessions);
|
||||||
return html`
|
return html`
|
||||||
<div class="ai-session-history">
|
<div class="ai-session-history">
|
||||||
${this.renderSessionGroup('Today', groupedSessions.today)}
|
${this.renderSessionGroup('Today', groupedSessions.today)}
|
||||||
|
|||||||
Reference in New Issue
Block a user