fix(core): improve performance (#6345)

This commit is contained in:
EYHN 2024-03-27 14:01:54 +00:00
parent 710edd28db
commit ba9dad95b4
No known key found for this signature in database
GPG Key ID: 46C9E26A75AB276C
6 changed files with 66 additions and 40 deletions

View File

@ -5,20 +5,22 @@ import type {
OperatorFunction,
Subscription,
TeardownLogic,
ThrottleConfig,
} from 'rxjs';
import {
BehaviorSubject,
combineLatest,
distinctUntilChanged,
EMPTY,
filter,
map,
mergeMap,
Observable,
of,
scan,
skip,
Subject,
switchMap,
throttleTime,
} from 'rxjs';
const logger = new DebugLogger('livedata');
@ -97,11 +99,10 @@ export class LiveData<T = unknown>
? upstream$
: stream$ =>
stream$.pipe(
filter(
(op): op is Exclude<LiveDataOperation, 'set'> => op !== 'set'
),
switchMap(v => {
if (v === 'get') {
mergeMap(v => {
if (v === 'set') {
return EMPTY;
} else if (v === 'get') {
return of('watch' as const, 'unwatch' as const);
} else {
return of(v);
@ -333,6 +334,23 @@ export class LiveData<T = unknown>
return sub$;
}
distinctUntilChanged(comparator?: (previous: T, current: T) => boolean) {
return LiveData.from(
this.pipe(distinctUntilChanged(comparator)),
null as any
);
}
throttleTime(
duration: number,
{ trailing = true, leading = true }: ThrottleConfig = {}
) {
return LiveData.from(
this.pipe(throttleTime(duration, undefined, { trailing, leading })),
null as any
);
}
// eslint-disable-next-line rxjs/finnish
asObservable(): Observable<T> {
return new Observable<T>(subscriber => {

View File

@ -8,6 +8,7 @@ import type { Workspace, WorkspaceLocalState } from '../workspace';
export type PageMode = 'edgeless' | 'page';
export class PageRecord {
meta: Partial<DocMeta> | null = null;
constructor(
public readonly id: string,
private readonly workspace: Workspace,
@ -15,15 +16,14 @@ export class PageRecord {
) {}
meta$ = LiveData.from<Partial<DocMeta>>(
new Observable<DocMeta>(subscriber => {
new Observable<Partial<DocMeta>>(subscriber => {
const emit = () => {
const meta = this.workspace.docCollection.meta.docMetas.find(
page => page.id === this.id
);
if (meta === undefined) {
return;
if (this.meta === null) {
// getDocMeta is heavy, so we cache the doc meta reference
this.meta =
this.workspace.docCollection.meta.getDocMeta(this.id) || null;
}
subscriber.next(meta);
subscriber.next({ ...this.meta });
};
emit();

View File

@ -1,3 +1,4 @@
import type { Tag } from '@affine/core/modules/tag';
import { TagService } from '@affine/core/modules/tag';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { FavoritedIcon, FavoriteIcon } from '@blocksuite/icons';
@ -28,7 +29,7 @@ const GroupLabel = ({
id,
}: {
id: string;
label: string;
label: ReactNode;
count: number;
icon?: ReactNode;
}) => (
@ -115,30 +116,38 @@ export const useDateGroupDefinitions = <T extends ListItem>(
[key, t]
);
};
const GroupTagLabel = ({ tag, count }: { tag: Tag; count: number }) => {
const tagValue = useLiveData(tag.value$);
const tagColor = useLiveData(tag.color$);
return (
<GroupLabel
id={tag.id}
label={tagValue}
count={count}
icon={
<div
className={styles.tagIcon}
style={{
backgroundColor: tagColor,
}}
></div>
}
></GroupLabel>
);
};
export const useTagGroupDefinitions = (): ItemGroupDefinition<ListItem>[] => {
const tagService = useService(TagService);
const tagMetas = useLiveData(tagService.tagMetas$);
const tags = useLiveData(tagService.tags$);
return useMemo(() => {
return tagMetas.map(tag => ({
return tags.map(tag => ({
id: tag.id,
label: count => (
<GroupLabel
id={tag.title}
label={tag.title}
count={count}
icon={
<div
className={styles.tagIcon}
style={{
backgroundColor: tag.color,
}}
></div>
}
/>
),
label: count => {
return <GroupTagLabel tag={tag} count={count} />;
},
match: item => (item as DocMeta).tags?.includes(tag.id),
}));
}, [tagMetas]);
}, [tags]);
};
export const useFavoriteGroupDefinitions = <

View File

@ -4,8 +4,9 @@ import { useMemo } from 'react';
export function useDocEngineStatus() {
const workspace = useService(Workspace);
const engineState = useLiveData(workspace.engine.docEngineState$);
const engineState = useLiveData(
workspace.engine.docEngineState$.throttleTime(100)
);
const progress =
(engineState.total - engineState.syncing) / engineState.total;

View File

@ -196,11 +196,9 @@ const JournalDailyCountBlock = ({ date }: JournalBlockProps) => {
(field: 'createDate' | 'updatedDate') => {
return sortPagesByDate(
pageRecords.filter(pageRecord => {
if (pageRecord.meta$.value.trash) return false;
return (
pageRecord.meta$.value[field] &&
dayjs(pageRecord.meta$.value[field]).isSame(date, 'day')
);
const meta = pageRecord.meta$.value;
if (meta.trash) return false;
return meta[field] && dayjs(meta[field]).isSame(date, 'day');
}),
field
);

View File

@ -73,7 +73,7 @@ export const Component = (): ReactElement => {
// avoid doing operation, before workspace is loaded
const isRootDocReady =
useLiveData(workspace?.engine.rootDocState$)?.ready ?? false;
useLiveData(workspace?.engine.rootDocState$.map(v => v.ready)) ?? false;
// if listLoading is false, we can show 404 page, otherwise we should show loading page.
if (listLoading === false && meta === undefined) {