mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-03 18:40:00 +08:00
feat(infra): new doc sync engine (#6205)
https://github.com/toeverything/AFFiNE/blob/eyhn/feat/new-sync/packages/common/infra/src/workspace/engine/doc/README.md
This commit is contained in:
+1
-1
@@ -31,7 +31,7 @@ export const ExportPanel = ({
|
||||
setSaving(true);
|
||||
try {
|
||||
if (isOnline) {
|
||||
await workspace.engine.sync.waitForSynced();
|
||||
await workspace.engine.waitForSynced();
|
||||
await workspace.engine.blob.sync();
|
||||
}
|
||||
|
||||
|
||||
+26
@@ -8,6 +8,8 @@ import { useWorkspace } from '@affine/core/hooks/use-workspace';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { DeleteLeaveWorkspace } from './delete-leave-workspace';
|
||||
import { EnableCloudPanel } from './enable-cloud';
|
||||
@@ -29,6 +31,17 @@ export const WorkspaceSettingDetail = (props: WorkspaceSettingDetailProps) => {
|
||||
|
||||
const workspaceInfo = useWorkspaceInfo(workspaceMetadata);
|
||||
|
||||
const handleResetSyncStatus = useCallback(() => {
|
||||
workspace?.engine.doc
|
||||
.resetSyncStatus()
|
||||
.then(() => {
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, [workspace]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
@@ -64,6 +77,19 @@ export const WorkspaceSettingDetail = (props: WorkspaceSettingDetailProps) => {
|
||||
)}
|
||||
<SettingWrapper>
|
||||
<DeleteLeaveWorkspace {...props} />
|
||||
<SettingRow
|
||||
name={
|
||||
<span style={{ color: 'var(--affine-text-secondary-color)' }}>
|
||||
{t['com.affine.resetSyncStatus.button']()}
|
||||
</span>
|
||||
}
|
||||
desc={t['com.affine.resetSyncStatus.description']()}
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={handleResetSyncStatus}
|
||||
data-testid="reset-sync-status"
|
||||
>
|
||||
<ArrowRightSmallIcon />
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
</>
|
||||
);
|
||||
|
||||
+4
-11
@@ -5,13 +5,12 @@ import { Button } from '@affine/component/ui/button';
|
||||
import { Upload } from '@affine/core/components/pure/file-upload';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useWorkspaceBlobObjectUrl } from '@affine/core/hooks/use-workspace-blob';
|
||||
import { useWorkspaceStatus } from '@affine/core/hooks/use-workspace-status';
|
||||
import { validateAndReduceImage } from '@affine/core/utils/reduce-image';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CameraIcon } from '@blocksuite/icons';
|
||||
import type { Workspace } from '@toeverything/infra';
|
||||
import { SyncPeerStep } from '@toeverything/infra';
|
||||
import { useLiveData } from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import {
|
||||
type KeyboardEvent,
|
||||
@@ -32,13 +31,7 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
const workspaceIsLoading =
|
||||
useWorkspaceStatus(
|
||||
workspace,
|
||||
status =>
|
||||
!status.engine.sync.local ||
|
||||
status.engine.sync.local?.step <= SyncPeerStep.LoadingRootDoc
|
||||
) ?? true;
|
||||
const workspaceIsReady = useLiveData(workspace?.engine.rootDocState)?.ready;
|
||||
|
||||
const [avatarBlob, setAvatarBlob] = useState<string | null>(null);
|
||||
const [name, setName] = useState('');
|
||||
@@ -158,7 +151,7 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
[pushNotification, setWorkspaceAvatar]
|
||||
);
|
||||
|
||||
const canAdjustAvatar = !workspaceIsLoading && avatarUrl && isOwner;
|
||||
const canAdjustAvatar = workspaceIsReady && avatarUrl && isOwner;
|
||||
|
||||
return (
|
||||
<div className={style.profileWrapper}>
|
||||
@@ -194,7 +187,7 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
|
||||
<div className={style.label}>{t['Workspace Name']()}</div>
|
||||
<FlexWrapper alignItems="center" flexGrow="1">
|
||||
<Input
|
||||
disabled={workspaceIsLoading || !isOwner}
|
||||
disabled={!workspaceIsReady || !isOwner}
|
||||
value={input}
|
||||
style={{ width: 280, height: 32 }}
|
||||
data-testid="workspace-name-input"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
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 { useDocEngineStatus } from '@affine/core/hooks/affine/use-doc-engine-status';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { DocMeta } from '@blocksuite/store';
|
||||
import { SyncEngineStep } from '@toeverything/infra';
|
||||
import type { CommandCategory } from '@toeverything/infra/command';
|
||||
import clsx from 'clsx';
|
||||
import { Command } from 'cmdk';
|
||||
@@ -163,7 +162,7 @@ export const CMDKContainer = ({
|
||||
const [value, setValue] = useAtom(cmdkValueAtom);
|
||||
const isInEditor = pageMeta !== undefined;
|
||||
const [opening, setOpening] = useState(open);
|
||||
const { syncEngineStatus, progress } = useSyncEngineStatus();
|
||||
const { syncing, progress } = useDocEngineStatus();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// fix list height animation on opening
|
||||
@@ -205,8 +204,7 @@ export const CMDKContainer = ({
|
||||
inEditor: isInEditor,
|
||||
})}
|
||||
>
|
||||
{!syncEngineStatus ||
|
||||
syncEngineStatus.step === SyncEngineStep.Syncing ? (
|
||||
{syncing ? (
|
||||
<Loading
|
||||
size={24}
|
||||
progress={progress ? Math.max(progress, 0.2) : undefined}
|
||||
|
||||
+15
-41
@@ -3,8 +3,8 @@ import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Loading } from '@affine/component/ui/loading';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useDocEngineStatus } from '@affine/core/hooks/affine/use-doc-engine-status';
|
||||
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';
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
NoNetworkIcon,
|
||||
UnsyncIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { SyncEngineStep, Workspace } from '@toeverything/infra';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { debounce } from 'lodash-es';
|
||||
@@ -94,8 +94,7 @@ const useSyncEngineSyncProgress = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const isOnline = useSystemOnline();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
const { syncEngineStatus, setSyncEngineStatus, progress } =
|
||||
useSyncEngineStatus();
|
||||
const { syncing, progress, retrying, errorMessage } = useDocEngineStatus();
|
||||
const [isOverCapacity, setIsOverCapacity] = useState(false);
|
||||
|
||||
const currentWorkspace = useService(Workspace);
|
||||
@@ -111,19 +110,6 @@ const useSyncEngineSyncProgress = () => {
|
||||
|
||||
// debounce sync engine status
|
||||
useEffect(() => {
|
||||
setSyncEngineStatus(currentWorkspace.engine.sync.status);
|
||||
const disposable = currentWorkspace.engine.sync.onStatusChange.on(
|
||||
debounce(
|
||||
status => {
|
||||
setSyncEngineStatus(status);
|
||||
},
|
||||
300,
|
||||
{
|
||||
maxWait: 500,
|
||||
trailing: true,
|
||||
}
|
||||
)
|
||||
);
|
||||
const disposableOverCapacity =
|
||||
currentWorkspace.engine.blob.onStatusChange.on(
|
||||
debounce(status => {
|
||||
@@ -153,17 +139,9 @@ const useSyncEngineSyncProgress = () => {
|
||||
})
|
||||
);
|
||||
return () => {
|
||||
disposable?.dispose();
|
||||
disposableOverCapacity?.dispose();
|
||||
};
|
||||
}, [
|
||||
currentWorkspace,
|
||||
isOwner,
|
||||
jumpToPricePlan,
|
||||
pushNotification,
|
||||
setSyncEngineStatus,
|
||||
t,
|
||||
]);
|
||||
}, [currentWorkspace, isOwner, jumpToPricePlan, pushNotification, t]);
|
||||
|
||||
const content = useMemo(() => {
|
||||
// TODO: add i18n
|
||||
@@ -176,21 +154,15 @@ const useSyncEngineSyncProgress = () => {
|
||||
if (!isOnline) {
|
||||
return 'Disconnected, please check your network connection';
|
||||
}
|
||||
if (!syncEngineStatus || syncEngineStatus.step === SyncEngineStep.Syncing) {
|
||||
if (syncing) {
|
||||
return (
|
||||
`Syncing with AFFiNE Cloud` +
|
||||
(progress ? ` (${Math.floor(progress * 100)}%)` : '')
|
||||
);
|
||||
} else if (
|
||||
syncEngineStatus &&
|
||||
syncEngineStatus.step < SyncEngineStep.Syncing
|
||||
) {
|
||||
return (
|
||||
syncEngineStatus.error ||
|
||||
'Disconnected, please check your network connection'
|
||||
);
|
||||
} else if (retrying && errorMessage) {
|
||||
return `${errorMessage}, reconnecting.`;
|
||||
}
|
||||
if (syncEngineStatus.retrying) {
|
||||
if (retrying) {
|
||||
return 'Sync disconnected due to unexpected issues, reconnecting.';
|
||||
}
|
||||
if (isOverCapacity) {
|
||||
@@ -199,29 +171,31 @@ const useSyncEngineSyncProgress = () => {
|
||||
return 'Synced with AFFiNE Cloud';
|
||||
}, [
|
||||
currentWorkspace.flavour,
|
||||
errorMessage,
|
||||
isOnline,
|
||||
isOverCapacity,
|
||||
progress,
|
||||
syncEngineStatus,
|
||||
retrying,
|
||||
syncing,
|
||||
]);
|
||||
|
||||
const CloudWorkspaceSyncStatus = useCallback(() => {
|
||||
if (!syncEngineStatus || syncEngineStatus.step === SyncEngineStep.Syncing) {
|
||||
if (syncing) {
|
||||
return SyncingWorkspaceStatus({
|
||||
progress: progress ? Math.max(progress, 0.2) : undefined,
|
||||
});
|
||||
} else if (syncEngineStatus.retrying || isOverCapacity) {
|
||||
} else if (retrying) {
|
||||
return UnSyncWorkspaceStatus();
|
||||
} else {
|
||||
return CloudWorkspaceStatus();
|
||||
}
|
||||
}, [isOverCapacity, progress, syncEngineStatus]);
|
||||
}, [progress, retrying, syncing]);
|
||||
|
||||
return {
|
||||
message: content,
|
||||
icon:
|
||||
currentWorkspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? (
|
||||
!isOnline || syncEngineStatus?.error ? (
|
||||
!isOnline ? (
|
||||
<OfflineStatus />
|
||||
) : (
|
||||
<CloudWorkspaceSyncStatus />
|
||||
|
||||
Reference in New Issue
Block a user