mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-18 02:26:21 +08:00
refactor(core): refactor tag to use di (#6079)
use case ``` const tagService = useService(TagService); const tags = useLiveData(tagService.tags); const currentTagLiveData = tagService.tagByTagId(tagId); const currentTag = useLiveData(currentTagLiveData); ```
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
GlobalCache,
|
||||
GlobalState,
|
||||
PageRecordList,
|
||||
type ServiceCollection,
|
||||
Workspace,
|
||||
WorkspaceScope,
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
} from './infra-web/storage';
|
||||
import { Navigator } from './navigation';
|
||||
import { RightSidebar } from './right-sidebar/entities/right-sidebar';
|
||||
import { TagService } from './tag';
|
||||
import { Workbench } from './workbench';
|
||||
import {
|
||||
CurrentWorkspaceService,
|
||||
@@ -29,7 +31,8 @@ export function configureBusinessServices(services: ServiceCollection) {
|
||||
.add(RightSidebar)
|
||||
.add(WorkspacePropertiesAdapter, [Workspace])
|
||||
.add(CollectionService, [Workspace])
|
||||
.add(WorkspaceLegacyProperties, [Workspace]);
|
||||
.add(WorkspaceLegacyProperties, [Workspace])
|
||||
.add(TagService, [WorkspaceLegacyProperties, PageRecordList]);
|
||||
}
|
||||
|
||||
export function configureWebInfraServices(services: ServiceCollection) {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import type { Tag as TagSchema } from '@affine/env/filter';
|
||||
import { LiveData, type PageRecordList } from '@toeverything/infra';
|
||||
|
||||
import type { WorkspaceLegacyProperties } from '../../workspace';
|
||||
|
||||
export class Tag {
|
||||
constructor(
|
||||
readonly id: string,
|
||||
private readonly properties: WorkspaceLegacyProperties,
|
||||
private readonly pageRecordList: PageRecordList
|
||||
) {}
|
||||
|
||||
private readonly tagOption = this.properties.tagOptions$.map(
|
||||
tags => tags.find(tag => tag.id === this.id) as TagSchema
|
||||
);
|
||||
|
||||
value = this.tagOption.map(tag => tag?.value || '');
|
||||
|
||||
color = this.tagOption.map(tag => tag?.color || '');
|
||||
|
||||
createDate = this.tagOption.map(tag => tag?.createDate || Date.now());
|
||||
|
||||
updateDate = this.tagOption.map(tag => tag?.updateDate || Date.now());
|
||||
|
||||
rename(value: string) {
|
||||
this.properties.updateTagOption(this.id, {
|
||||
id: this.id,
|
||||
value,
|
||||
color: this.color.value,
|
||||
createDate: this.createDate.value,
|
||||
updateDate: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
changeColor(color: string) {
|
||||
this.properties.updateTagOption(this.id, {
|
||||
id: this.id,
|
||||
value: this.value.value,
|
||||
color,
|
||||
createDate: this.createDate.value,
|
||||
updateDate: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
tag(pageId: string) {
|
||||
const pageRecord = this.pageRecordList.record(pageId).value;
|
||||
if (!pageRecord) {
|
||||
return;
|
||||
}
|
||||
pageRecord?.setMeta({
|
||||
tags: [...pageRecord.meta.value.tags, this.id],
|
||||
});
|
||||
}
|
||||
|
||||
untag(pageId: string) {
|
||||
const pageRecord = this.pageRecordList.record(pageId).value;
|
||||
if (!pageRecord) {
|
||||
return;
|
||||
}
|
||||
pageRecord?.setMeta({
|
||||
tags: pageRecord.meta.value.tags.filter(tagId => tagId !== this.id),
|
||||
});
|
||||
}
|
||||
|
||||
readonly pageIds = LiveData.computed(get => {
|
||||
const pages = get(this.pageRecordList.records);
|
||||
return pages
|
||||
.filter(page => get(page.meta).tags.includes(this.id))
|
||||
.map(page => page.id);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// hack: map var(--affine-tag-xxx) colors to var(--affine-palette-line-xxx)
|
||||
export const tagColorMap = (color: string) => {
|
||||
const mapping: Record<string, string> = {
|
||||
'var(--affine-tag-red)': 'var(--affine-palette-line-red)',
|
||||
'var(--affine-tag-teal)': 'var(--affine-palette-line-green)',
|
||||
'var(--affine-tag-blue)': 'var(--affine-palette-line-blue)',
|
||||
'var(--affine-tag-yellow)': 'var(--affine-palette-line-yellow)',
|
||||
'var(--affine-tag-pink)': 'var(--affine-palette-line-magenta)',
|
||||
'var(--affine-tag-white)': 'var(--affine-palette-line-grey)',
|
||||
'var(--affine-tag-gray)': 'var(--affine-palette-line-grey)',
|
||||
'var(--affine-tag-orange)': 'var(--affine-palette-line-orange)',
|
||||
'var(--affine-tag-purple)': 'var(--affine-palette-line-purple)',
|
||||
'var(--affine-tag-green)': 'var(--affine-palette-line-green)',
|
||||
};
|
||||
return mapping[color] || color;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export { Tag } from './entities/tag';
|
||||
export { tagColorMap } from './entities/utils';
|
||||
export { TagService } from './service/tag';
|
||||
@@ -0,0 +1,85 @@
|
||||
import { LiveData, type PageRecordList } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import type { WorkspaceLegacyProperties } from '../../workspace';
|
||||
import { Tag } from '../entities/tag';
|
||||
|
||||
export class TagService {
|
||||
constructor(
|
||||
private readonly properties: WorkspaceLegacyProperties,
|
||||
private readonly pageRecordList: PageRecordList
|
||||
) {}
|
||||
|
||||
readonly tags = this.properties.tagOptions$.map(tags =>
|
||||
tags.map(tag => new Tag(tag.id, this.properties, this.pageRecordList))
|
||||
);
|
||||
|
||||
createTag(value: string, color: string) {
|
||||
const newId = nanoid();
|
||||
this.properties.updateTagOptions([
|
||||
...this.properties.tagOptions$.value,
|
||||
{
|
||||
id: newId,
|
||||
value,
|
||||
color,
|
||||
createDate: Date.now(),
|
||||
updateDate: Date.now(),
|
||||
},
|
||||
]);
|
||||
const newTag = new Tag(newId, this.properties, this.pageRecordList);
|
||||
return newTag;
|
||||
}
|
||||
|
||||
deleteTag(tagId: string) {
|
||||
this.properties.removeTagOption(tagId);
|
||||
}
|
||||
|
||||
tagsByPageId(pageId: string) {
|
||||
return LiveData.computed(get => {
|
||||
const pageRecord = get(this.pageRecordList.record(pageId));
|
||||
if (!pageRecord) return [];
|
||||
const tagIds = get(pageRecord.meta).tags;
|
||||
|
||||
return get(this.tags).filter(tag => tagIds.includes(tag.id));
|
||||
});
|
||||
}
|
||||
|
||||
tagIdsByPageId(pageId: string) {
|
||||
return this.tagsByPageId(pageId).map(tags => tags.map(tag => tag.id));
|
||||
}
|
||||
|
||||
tagByTagId(tagId?: string) {
|
||||
return this.tags.map(tags => tags.find(tag => tag.id === tagId));
|
||||
}
|
||||
|
||||
tagMetas = LiveData.computed(get => {
|
||||
return get(this.tags).map(tag => {
|
||||
return {
|
||||
id: tag.id,
|
||||
title: get(tag.value),
|
||||
color: get(tag.color),
|
||||
pageCount: get(tag.pageIds).length,
|
||||
createDate: get(tag.createDate),
|
||||
updatedDate: get(tag.updateDate),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
private filterFn(value: string, query?: string) {
|
||||
const trimmedQuery = query?.trim().toLowerCase() ?? '';
|
||||
const trimmedValue = value.trim().toLowerCase();
|
||||
return trimmedValue.includes(trimmedQuery);
|
||||
}
|
||||
|
||||
filterTagsByName(name: string) {
|
||||
return LiveData.computed(get => {
|
||||
return get(this.tags).filter(tag => this.filterFn(get(tag.value), name));
|
||||
});
|
||||
}
|
||||
|
||||
tagByTagValue(value: string) {
|
||||
return LiveData.computed(get => {
|
||||
return get(this.tags).find(tag => this.filterFn(get(tag.value), value));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { DocsPropertiesMeta, Tag } from '@blocksuite/store';
|
||||
import type { Tag } from '@affine/env/filter';
|
||||
import type { DocsPropertiesMeta } from '@blocksuite/store';
|
||||
import { LiveData } from '@toeverything/infra/livedata';
|
||||
import type { Workspace } from '@toeverything/infra/workspace';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
Reference in New Issue
Block a user