feat(core): optimize tag performance (#12719)

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

## Summary by CodeRabbit

- **Refactor**
  - Improved tag options management to use a reactive, real-time approach, ensuring tag options are always up to date throughout the application.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
EYHN
2025-06-05 07:13:30 +00:00
parent c1930c5937
commit 5e05952f6e
@@ -3,10 +3,11 @@ import {
LiveData, LiveData,
Store, Store,
yjsGetPath, yjsGetPath,
yjsObserveDeep,
yjsObservePath, yjsObservePath,
} from '@toeverything/infra'; } from '@toeverything/infra';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { map, Observable, switchMap } from 'rxjs'; import { map, switchMap } from 'rxjs';
import { Array as YArray } from 'yjs'; import { Array as YArray } from 'yjs';
import type { WorkspaceService } from '../../workspace'; import type { WorkspaceService } from '../../workspace';
@@ -24,15 +25,22 @@ export class TagStore extends Store {
get properties() { get properties() {
return this.workspaceService.workspace.docCollection.meta.properties; return this.workspaceService.workspace.docCollection.meta.properties;
} }
get tagOptions() {
return this.properties.tags?.options ?? [];
}
tagOptions$ = LiveData.from( tagOptions$ = LiveData.from(
new Observable<Tag[]>(sub => { yjsGetPath(
return this.subscribe(() => sub.next(this.tagOptions)); this.workspaceService.workspace.rootYDoc.getMap('meta'),
}), 'properties.tags.options'
this.tagOptions ).pipe(
switchMap(yjsObserveDeep),
map(tagOptions => {
if (tagOptions instanceof YArray) {
return tagOptions.toJSON();
} else {
return [];
}
})
),
[]
); );
subscribe(cb: () => void) { subscribe(cb: () => void) {
@@ -82,12 +90,14 @@ export class TagStore extends Store {
}; };
updateTagOption = (id: string, option: Tag) => { updateTagOption = (id: string, option: Tag) => {
this.updateTagOptions(this.tagOptions.map(o => (o.id === id ? option : o))); this.updateTagOptions(
this.tagOptions$.value.map(o => (o.id === id ? option : o))
);
}; };
removeTagOption = (id: string) => { removeTagOption = (id: string) => {
this.workspaceService.workspace.docCollection.doc.transact(() => { this.workspaceService.workspace.docCollection.doc.transact(() => {
this.updateTagOptions(this.tagOptions.filter(o => o.id !== id)); this.updateTagOptions(this.tagOptions$.value.filter(o => o.id !== id));
// need to remove tag from all pages // need to remove tag from all pages
this.workspaceService.workspace.docCollection.docs.forEach(doc => { this.workspaceService.workspace.docCollection.docs.forEach(doc => {
const tags = doc.meta?.tags ?? []; const tags = doc.meta?.tags ?? [];