diff --git a/packages/frontend/component/src/ui/loading/loading.tsx b/packages/frontend/component/src/ui/loading/loading.tsx index 49e72705c..34195e5ec 100644 --- a/packages/frontend/component/src/ui/loading/loading.tsx +++ b/packages/frontend/component/src/ui/loading/loading.tsx @@ -5,9 +5,14 @@ import { loading, speedVar } from './styles.css'; export interface LoadingProps { size?: number; speed?: number; + progress?: number; } -export const Loading = ({ size, speed = 1.2 }: LoadingProps) => { +export const Loading = ({ + size, + speed = 1.2, + progress = 0.2, +}: LoadingProps) => { return ( { }), }} > - - ); diff --git a/packages/frontend/component/src/ui/loading/styles.css.ts b/packages/frontend/component/src/ui/loading/styles.css.ts index 465f98986..94f92627c 100644 --- a/packages/frontend/component/src/ui/loading/styles.css.ts +++ b/packages/frontend/component/src/ui/loading/styles.css.ts @@ -13,5 +13,6 @@ export const loading = style({ }, textRendering: 'optimizeLegibility', WebkitFontSmoothing: 'antialiased', + transform: 'rotate(-90deg)', animation: `${rotate} ${speedVar} infinite linear`, }); 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 ceff61e90..1fef59aa3 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 @@ -15,7 +15,7 @@ import { import { useWorkspaceBlobObjectUrl } from '@toeverything/hooks/use-workspace-blob'; import { useWorkspaceInfo } from '@toeverything/hooks/use-workspace-info'; import { useAtomValue } from 'jotai'; -import { debounce } from 'lodash-es'; +import { debounce, mean } from 'lodash-es'; import { forwardRef, type HTMLAttributes, @@ -45,10 +45,10 @@ const CloudWorkspaceStatus = () => { ); }; -const SyncingWorkspaceStatus = () => { +const SyncingWorkspaceStatus = ({ progress }: { progress?: number }) => { return ( <> - + Syncing... ); @@ -85,7 +85,7 @@ const OfflineStatus = () => { ); }; -const WorkspaceStatus = () => { +const useSyncEngineSyncProgress = () => { const isOnline = useSystemOnline(); const [syncEngineStatus, setSyncEngineStatus] = @@ -106,6 +106,24 @@ const WorkspaceStatus = () => { }; }, [currentWorkspace]); + 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]); + const content = useMemo(() => { // TODO: add i18n if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) { @@ -118,38 +136,51 @@ const WorkspaceStatus = () => { return 'Disconnected, please check your network connection'; } if (!syncEngineStatus || syncEngineStatus.step === SyncEngineStep.Syncing) { - return 'Syncing with AFFiNE Cloud'; + return ( + `Syncing with AFFiNE Cloud` + + (progress ? ` (${Math.floor(progress * 100)}%)` : '') + ); } if (syncEngineStatus.retrying) { return 'Sync disconnected due to unexpected issues, reconnecting.'; } return 'Synced with AFFiNE Cloud'; - }, [currentWorkspace.flavour, isOnline, syncEngineStatus]); + }, [currentWorkspace.flavour, isOnline, progress, syncEngineStatus]); const CloudWorkspaceSyncStatus = useCallback(() => { if (!syncEngineStatus || syncEngineStatus.step === SyncEngineStep.Syncing) { - return SyncingWorkspaceStatus(); + return SyncingWorkspaceStatus({ + progress: progress ? Math.max(progress, 0.2) : undefined, + }); } else if (syncEngineStatus.retrying) { return UnSyncWorkspaceStatus(); } else { return CloudWorkspaceStatus(); } - }, [syncEngineStatus]); + }, [progress, syncEngineStatus]); + + return { + message: content, + icon: + currentWorkspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? ( + !isOnline ? ( + + ) : ( + + ) + ) : ( + + ), + }; +}; + +const WorkspaceStatus = () => { + const { message, icon } = useSyncEngineSyncProgress(); return (
- - - {currentWorkspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? ( - !isOnline ? ( - - ) : ( - - ) - ) : ( - - )} - + + {icon}
);