mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-22 18:42:48 +03:00
fix(core): improve performance (#6345)
This commit is contained in:
parent
710edd28db
commit
ba9dad95b4
@ -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 => {
|
||||
|
@ -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();
|
||||
|
@ -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 = <
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user