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, OperatorFunction,
Subscription, Subscription,
TeardownLogic, TeardownLogic,
ThrottleConfig,
} from 'rxjs'; } from 'rxjs';
import { import {
BehaviorSubject, BehaviorSubject,
combineLatest, combineLatest,
distinctUntilChanged, distinctUntilChanged,
EMPTY, EMPTY,
filter,
map, map,
mergeMap,
Observable, Observable,
of, of,
scan, scan,
skip, skip,
Subject, Subject,
switchMap, switchMap,
throttleTime,
} from 'rxjs'; } from 'rxjs';
const logger = new DebugLogger('livedata'); const logger = new DebugLogger('livedata');
@ -97,11 +99,10 @@ export class LiveData<T = unknown>
? upstream$ ? upstream$
: stream$ => : stream$ =>
stream$.pipe( stream$.pipe(
filter( mergeMap(v => {
(op): op is Exclude<LiveDataOperation, 'set'> => op !== 'set' if (v === 'set') {
), return EMPTY;
switchMap(v => { } else if (v === 'get') {
if (v === 'get') {
return of('watch' as const, 'unwatch' as const); return of('watch' as const, 'unwatch' as const);
} else { } else {
return of(v); return of(v);
@ -333,6 +334,23 @@ export class LiveData<T = unknown>
return sub$; 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 // eslint-disable-next-line rxjs/finnish
asObservable(): Observable<T> { asObservable(): Observable<T> {
return new Observable<T>(subscriber => { return new Observable<T>(subscriber => {

View File

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

View File

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

View File

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

View File

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

View File

@ -73,7 +73,7 @@ export const Component = (): ReactElement => {
// avoid doing operation, before workspace is loaded // avoid doing operation, before workspace is loaded
const isRootDocReady = 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 is false, we can show 404 page, otherwise we should show loading page.
if (listLoading === false && meta === undefined) { if (listLoading === false && meta === undefined) {