diff --git a/packages/frontend/core/src/atoms/sync-engine-status.ts b/packages/frontend/core/src/atoms/sync-engine-status.ts new file mode 100644 index 0000000000..8cbc093635 --- /dev/null +++ b/packages/frontend/core/src/atoms/sync-engine-status.ts @@ -0,0 +1,4 @@ +import type { SyncEngineStatus } from '@toeverything/infra'; +import { atom } from 'jotai'; + +export const syncEngineStatusAtom = atom(null); diff --git a/packages/frontend/core/src/components/pure/cmdk/main.css.ts b/packages/frontend/core/src/components/pure/cmdk/main.css.ts index ea4eea89db..493168f6d7 100644 --- a/packages/frontend/core/src/components/pure/cmdk/main.css.ts +++ b/packages/frontend/core/src/components/pure/cmdk/main.css.ts @@ -5,18 +5,16 @@ export const commandsContainer = style({ height: 'calc(100% - 65px)', padding: '8px 6px 18px 6px', }); -export const searchInput = style({ +export const searchInputContainer = style({ height: 66, - color: cssVar('textPrimaryColor'), - fontSize: cssVar('fontH5'), - padding: '21px 24px', + padding: '18px 16px', marginBottom: '8px', width: '100%', + display: 'flex', + alignItems: 'center', + gap: 12, borderBottom: `1px solid ${cssVar('borderColor')}`, flexShrink: 0, - '::placeholder': { - color: cssVar('textSecondaryColor'), - }, selectors: { '&.inEditor': { 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({ display: 'flex', alignItems: 'center', diff --git a/packages/frontend/core/src/components/pure/cmdk/main.tsx b/packages/frontend/core/src/components/pure/cmdk/main.tsx index 228eb0022f..626ceb8615 100644 --- a/packages/frontend/core/src/components/pure/cmdk/main.tsx +++ b/packages/frontend/core/src/components/pure/cmdk/main.tsx @@ -1,7 +1,10 @@ +import { Loading } from '@affine/component/ui/loading'; 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 { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { PageMeta } from '@blocksuite/store'; +import { SyncEngineStep } from '@toeverything/infra'; import type { CommandCategory } from '@toeverything/infra/command'; import clsx from 'clsx'; import { Command } from 'cmdk'; @@ -160,7 +163,7 @@ export const CMDKContainer = ({ const [value, setValue] = useAtom(cmdkValueAtom); const isInEditor = pageMeta !== undefined; const [opening, setOpening] = useState(open); - + const { syncEngineStatus, progress } = useSyncEngineStatus(); const inputRef = useRef(null); // fix list height animation on opening @@ -197,16 +200,29 @@ export const CMDKContainer = ({ ) : null} - + > + {!syncEngineStatus || + syncEngineStatus.step === SyncEngineStep.Syncing ? ( + + ) : null} + + + {children} diff --git a/packages/frontend/core/src/components/pure/workspace-slider-bar/workspace-card/index.tsx b/packages/frontend/core/src/components/pure/workspace-slider-bar/workspace-card/index.tsx index 8a4a121bf5..1dc8f75d0e 100644 --- a/packages/frontend/core/src/components/pure/workspace-slider-bar/workspace-card/index.tsx +++ b/packages/frontend/core/src/components/pure/workspace-slider-bar/workspace-card/index.tsx @@ -4,6 +4,7 @@ import { Loading } from '@affine/component/ui/loading'; import { Tooltip } from '@affine/component/ui/tooltip'; import { openSettingModalAtom } from '@affine/core/atoms'; 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 { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info'; import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant'; @@ -16,14 +17,10 @@ import { NoNetworkIcon, UnsyncIcon, } from '@blocksuite/icons'; -import { - type SyncEngineStatus, - SyncEngineStep, - Workspace, -} from '@toeverything/infra'; +import { SyncEngineStep, Workspace } from '@toeverything/infra'; import { useService } from '@toeverything/infra/di'; import { useSetAtom } from 'jotai'; -import { debounce, mean } from 'lodash-es'; +import { debounce } from 'lodash-es'; import { forwardRef, type HTMLAttributes, @@ -97,8 +94,8 @@ const useSyncEngineSyncProgress = () => { const t = useAFFiNEI18N(); const isOnline = useSystemOnline(); const pushNotification = useSetAtom(pushNotificationAtom); - const [syncEngineStatus, setSyncEngineStatus] = - useState(null); + const { syncEngineStatus, setSyncEngineStatus, progress } = + useSyncEngineStatus(); const [isOverCapacity, setIsOverCapacity] = useState(false); const currentWorkspace = useService(Workspace); @@ -159,25 +156,14 @@ const useSyncEngineSyncProgress = () => { disposable?.dispose(); disposableOverCapacity?.dispose(); }; - }, [currentWorkspace, isOwner, jumpToPricePlan, pushNotification, t]); - - 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]); + }, [ + currentWorkspace, + isOwner, + jumpToPricePlan, + pushNotification, + setSyncEngineStatus, + t, + ]); const content = useMemo(() => { // TODO: add i18n diff --git a/packages/frontend/core/src/hooks/affine/use-sync-engine-status.tsx b/packages/frontend/core/src/hooks/affine/use-sync-engine-status.tsx new file mode 100644 index 0000000000..358872194c --- /dev/null +++ b/packages/frontend/core/src/hooks/affine/use-sync-engine-status.tsx @@ -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] + ); +}