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