feat(core): add loading to quick search modal (#5785)
close AFF-285 add `useSyncEngineStatus` hooks add loading style <img width="977" alt="test1" src="https://github.com/toeverything/AFFiNE/assets/102217452/e8bf6714-e42b-4adf-a279-341ef5f5cfc0">
This commit is contained in:
4
packages/frontend/core/src/atoms/sync-engine-status.ts
Normal file
4
packages/frontend/core/src/atoms/sync-engine-status.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import type { SyncEngineStatus } from '@toeverything/infra';
|
||||||
|
import { atom } from 'jotai';
|
||||||
|
|
||||||
|
export const syncEngineStatusAtom = atom<SyncEngineStatus | null>(null);
|
||||||
@@ -5,18 +5,16 @@ export const commandsContainer = style({
|
|||||||
height: 'calc(100% - 65px)',
|
height: 'calc(100% - 65px)',
|
||||||
padding: '8px 6px 18px 6px',
|
padding: '8px 6px 18px 6px',
|
||||||
});
|
});
|
||||||
export const searchInput = style({
|
export const searchInputContainer = style({
|
||||||
height: 66,
|
height: 66,
|
||||||
color: cssVar('textPrimaryColor'),
|
padding: '18px 16px',
|
||||||
fontSize: cssVar('fontH5'),
|
|
||||||
padding: '21px 24px',
|
|
||||||
marginBottom: '8px',
|
marginBottom: '8px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 12,
|
||||||
borderBottom: `1px solid ${cssVar('borderColor')}`,
|
borderBottom: `1px solid ${cssVar('borderColor')}`,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
'::placeholder': {
|
|
||||||
color: cssVar('textSecondaryColor'),
|
|
||||||
},
|
|
||||||
selectors: {
|
selectors: {
|
||||||
'&.inEditor': {
|
'&.inEditor': {
|
||||||
paddingTop: '12px',
|
paddingTop: '12px',
|
||||||
@@ -24,6 +22,14 @@ export const searchInput = style({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
export const searchInput = style({
|
||||||
|
color: cssVar('textPrimaryColor'),
|
||||||
|
fontSize: cssVar('fontH5'),
|
||||||
|
width: '100%',
|
||||||
|
'::placeholder': {
|
||||||
|
color: cssVar('textSecondaryColor'),
|
||||||
|
},
|
||||||
|
});
|
||||||
export const pageTitleWrapper = style({
|
export const pageTitleWrapper = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
import { Loading } from '@affine/component/ui/loading';
|
||||||
import { formatDate } from '@affine/core/components/page-list';
|
import { formatDate } from '@affine/core/components/page-list';
|
||||||
|
import { useSyncEngineStatus } from '@affine/core/hooks/affine/use-sync-engine-status';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import type { PageMeta } from '@blocksuite/store';
|
import type { PageMeta } from '@blocksuite/store';
|
||||||
|
import { SyncEngineStep } from '@toeverything/infra';
|
||||||
import type { CommandCategory } from '@toeverything/infra/command';
|
import type { CommandCategory } from '@toeverything/infra/command';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { Command } from 'cmdk';
|
import { Command } from 'cmdk';
|
||||||
@@ -160,7 +163,7 @@ export const CMDKContainer = ({
|
|||||||
const [value, setValue] = useAtom(cmdkValueAtom);
|
const [value, setValue] = useAtom(cmdkValueAtom);
|
||||||
const isInEditor = pageMeta !== undefined;
|
const isInEditor = pageMeta !== undefined;
|
||||||
const [opening, setOpening] = useState(open);
|
const [opening, setOpening] = useState(open);
|
||||||
|
const { syncEngineStatus, progress } = useSyncEngineStatus();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
// fix list height animation on opening
|
// fix list height animation on opening
|
||||||
@@ -197,16 +200,29 @@ export const CMDKContainer = ({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
<div
|
||||||
|
className={clsx(className, styles.searchInputContainer, {
|
||||||
|
inEditor: isInEditor,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{!syncEngineStatus ||
|
||||||
|
syncEngineStatus.step === SyncEngineStep.Syncing ? (
|
||||||
|
<Loading
|
||||||
|
size={24}
|
||||||
|
progress={progress ? Math.max(progress, 0.2) : undefined}
|
||||||
|
speed={progress ? 0 : undefined}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
<Command.Input
|
<Command.Input
|
||||||
placeholder={t['com.affine.cmdk.placeholder']()}
|
placeholder={t['com.affine.cmdk.placeholder']()}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
{...rest}
|
{...rest}
|
||||||
value={query}
|
value={query}
|
||||||
onValueChange={onQueryChange}
|
onValueChange={onQueryChange}
|
||||||
className={clsx(className, styles.searchInput, {
|
className={clsx(className, styles.searchInput)}
|
||||||
inEditor: isInEditor,
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Command.List data-opening={opening ? true : undefined}>
|
<Command.List data-opening={opening ? true : undefined}>
|
||||||
{children}
|
{children}
|
||||||
</Command.List>
|
</Command.List>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Loading } from '@affine/component/ui/loading';
|
|||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner';
|
import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner';
|
||||||
|
import { useSyncEngineStatus } from '@affine/core/hooks/affine/use-sync-engine-status';
|
||||||
import { useWorkspaceBlobObjectUrl } from '@affine/core/hooks/use-workspace-blob';
|
import { useWorkspaceBlobObjectUrl } from '@affine/core/hooks/use-workspace-blob';
|
||||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||||
@@ -16,14 +17,10 @@ import {
|
|||||||
NoNetworkIcon,
|
NoNetworkIcon,
|
||||||
UnsyncIcon,
|
UnsyncIcon,
|
||||||
} from '@blocksuite/icons';
|
} from '@blocksuite/icons';
|
||||||
import {
|
import { SyncEngineStep, Workspace } from '@toeverything/infra';
|
||||||
type SyncEngineStatus,
|
|
||||||
SyncEngineStep,
|
|
||||||
Workspace,
|
|
||||||
} from '@toeverything/infra';
|
|
||||||
import { useService } from '@toeverything/infra/di';
|
import { useService } from '@toeverything/infra/di';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { debounce, mean } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
type HTMLAttributes,
|
type HTMLAttributes,
|
||||||
@@ -97,8 +94,8 @@ const useSyncEngineSyncProgress = () => {
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const isOnline = useSystemOnline();
|
const isOnline = useSystemOnline();
|
||||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||||
const [syncEngineStatus, setSyncEngineStatus] =
|
const { syncEngineStatus, setSyncEngineStatus, progress } =
|
||||||
useState<SyncEngineStatus | null>(null);
|
useSyncEngineStatus();
|
||||||
const [isOverCapacity, setIsOverCapacity] = useState(false);
|
const [isOverCapacity, setIsOverCapacity] = useState(false);
|
||||||
|
|
||||||
const currentWorkspace = useService(Workspace);
|
const currentWorkspace = useService(Workspace);
|
||||||
@@ -159,25 +156,14 @@ const useSyncEngineSyncProgress = () => {
|
|||||||
disposable?.dispose();
|
disposable?.dispose();
|
||||||
disposableOverCapacity?.dispose();
|
disposableOverCapacity?.dispose();
|
||||||
};
|
};
|
||||||
}, [currentWorkspace, isOwner, jumpToPricePlan, pushNotification, t]);
|
}, [
|
||||||
|
currentWorkspace,
|
||||||
const progress = useMemo(() => {
|
isOwner,
|
||||||
if (!syncEngineStatus?.remotes || syncEngineStatus?.remotes.length === 0) {
|
jumpToPricePlan,
|
||||||
return null;
|
pushNotification,
|
||||||
}
|
setSyncEngineStatus,
|
||||||
return mean(
|
t,
|
||||||
syncEngineStatus.remotes.map(peer => {
|
]);
|
||||||
if (!peer) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const totalTask =
|
|
||||||
peer.totalDocs + peer.pendingPullUpdates + peer.pendingPushUpdates;
|
|
||||||
const doneTask = peer.loadedDocs;
|
|
||||||
|
|
||||||
return doneTask / totalTask;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}, [syncEngineStatus?.remotes]);
|
|
||||||
|
|
||||||
const content = useMemo(() => {
|
const content = useMemo(() => {
|
||||||
// TODO: add i18n
|
// TODO: add i18n
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { syncEngineStatusAtom } from '@affine/core/atoms/sync-engine-status';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
import { mean } from 'lodash-es';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export function useSyncEngineStatus() {
|
||||||
|
const [syncEngineStatus, setSyncEngineStatus] = useAtom(syncEngineStatusAtom);
|
||||||
|
|
||||||
|
const progress = useMemo(() => {
|
||||||
|
if (!syncEngineStatus?.remotes || syncEngineStatus?.remotes.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mean(
|
||||||
|
syncEngineStatus.remotes.map(peer => {
|
||||||
|
if (!peer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const totalTask =
|
||||||
|
peer.totalDocs + peer.pendingPullUpdates + peer.pendingPushUpdates;
|
||||||
|
const doneTask = peer.loadedDocs;
|
||||||
|
|
||||||
|
return doneTask / totalTask;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, [syncEngineStatus?.remotes]);
|
||||||
|
|
||||||
|
return useMemo(
|
||||||
|
() => ({
|
||||||
|
syncEngineStatus,
|
||||||
|
setSyncEngineStatus,
|
||||||
|
progress,
|
||||||
|
}),
|
||||||
|
[progress, setSyncEngineStatus, syncEngineStatus]
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user