refactor(core): using computed data & optimizing data fetching timing & loading initial values (#12478)

## TL;DR

refactor workspace embedding:

* using computed data
* optimizing data fetching timing(constructor -> component mounted)
* set loading initial values to `true`

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved loading indicators and state handling for embedding settings, including a more accurate loading state for the embedding toggle.
- **Bug Fixes**
  - The embedding toggle now safely handles unknown or loading states and is disabled while loading, preventing unintended interactions.
- **Refactor**
  - Simplified pagination logic and optimized initial data fetching for a smoother user experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
yoyoyohamapi
2025-05-26 07:17:37 +00:00
parent d06bb0222f
commit da22391910
2 changed files with 26 additions and 25 deletions

View File

@@ -24,7 +24,6 @@ import {
import { COUNT_PER_PAGE } from '../constants';
import type { EmbeddingStore } from '../stores/embedding';
import type {
AttachmentFile,
IgnoredDoc,
LocalAttachmentFile,
PersistedAttachmentFile,
@@ -55,7 +54,7 @@ interface EmbeddingProgress {
}
export class Embedding extends Entity {
enabled$ = new LiveData<boolean>(false);
enabled$ = new LiveData<boolean | null>(null);
error$ = new LiveData<any>(null);
attachments$ = new LiveData<Attachments>({
edges: [],
@@ -66,36 +65,28 @@ export class Embedding extends Entity {
totalCount: 0,
});
ignoredDocs$ = new LiveData<IgnoredDocs>([]);
isEnabledLoading$ = new LiveData(false);
isAttachmentsLoading$ = new LiveData(false);
isIgnoredDocsLoading$ = new LiveData(false);
isEnabledLoading$ = new LiveData(true);
isAttachmentsLoading$ = new LiveData(true);
isIgnoredDocsLoading$ = new LiveData(true);
embeddingProgress$ = new LiveData<EmbeddingProgress | null>(null);
isEmbeddingProgressLoading$ = new LiveData(false);
isEmbeddingProgressLoading$ = new LiveData(true);
private readonly EMBEDDING_PROGRESS_POLL_INTERVAL = 3000;
private readonly stopEmbeddingProgress$ = new Subject<void>();
uploadingAttachments$ = new LiveData<LocalAttachmentFile[]>([]);
mergedAttachments$ = new LiveData<AttachmentFile[]>([]);
constructor(
private readonly workspaceService: WorkspaceService,
private readonly store: EmbeddingStore
) {
super();
this.getEnabled();
this.getAttachments({ first: COUNT_PER_PAGE, after: null });
this.getIgnoredDocs();
this.getEmbeddingProgress();
this.uploadingAttachments$.subscribe(() => this.updateMergedAttachments());
this.attachments$.subscribe(() => this.updateMergedAttachments());
this.updateMergedAttachments();
}
private updateMergedAttachments() {
const uploading = this.uploadingAttachments$.value;
const uploaded = this.attachments$.value.edges.map(edge => edge.node);
this.mergedAttachments$.next([...uploading, ...uploaded].slice(0, 10));
}
mergedAttachments$ = LiveData.computed(get => {
const uploading = get(this.uploadingAttachments$);
const uploaded = get(this.attachments$).edges.map(edge => edge.node);
return [...uploading, ...uploaded].slice(0, 10);
});
getEnabled = effect(
exhaustMap(() => {

View File

@@ -12,6 +12,7 @@ import { useLiveData, useService } from '@toeverything/infra';
import type React from 'react';
import { useCallback, useEffect } from 'react';
import { COUNT_PER_PAGE } from '../constants';
import { EmbeddingService } from '../services/embedding';
import { Attachments } from './attachments';
import EmbeddingProgress from './embedding-progress';
@@ -23,9 +24,7 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
const t = useI18n();
const embeddingService = useService(EmbeddingService);
const embeddingEnabled = useLiveData(embeddingService.embedding.enabled$);
const { pageInfo, totalCount } = useLiveData(
embeddingService.embedding.attachments$
);
const { totalCount } = useLiveData(embeddingService.embedding.attachments$);
const attachments = useLiveData(
embeddingService.embedding.mergedAttachments$
);
@@ -38,6 +37,9 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
embeddingService.embedding.isIgnoredDocsLoading$
);
const workspaceDialogService = useService(WorkspaceDialogService);
const isEnabledLoading = useLiveData(
embeddingService.embedding.isEnabledLoading$
);
const handleEmbeddingToggle = useCallback(
(checked: boolean) => {
@@ -74,10 +76,9 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
(offset: number) => {
embeddingService.embedding.getAttachments({
offset,
after: pageInfo.endCursor,
});
},
[embeddingService.embedding, pageInfo.endCursor]
[embeddingService.embedding]
);
const handleSelectDoc = useCallback(() => {
@@ -113,6 +114,14 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
useEffect(() => {
embeddingService.embedding.startEmbeddingProgressPolling();
embeddingService.embedding.getEnabled();
embeddingService.embedding.getAttachments({
first: COUNT_PER_PAGE,
after: null,
});
embeddingService.embedding.getIgnoredDocs();
embeddingService.embedding.getEmbeddingProgress();
return () => {
embeddingService.embedding.stopEmbeddingProgressPolling();
};
@@ -139,8 +148,9 @@ export const EmbeddingSettings: React.FC<EmbeddingSettingsProps> = () => {
>
<Switch
data-testid="workspace-embedding-setting-switch"
checked={embeddingEnabled}
checked={embeddingEnabled ?? false}
onChange={handleEmbeddingToggle}
disabled={isEnabledLoading}
/>
</SettingRow>