mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 15:16:28 +08:00
fix(workspace): data loss (hot-fix) (#6110)
This commit is contained in:
@@ -19,6 +19,7 @@ export interface SyncPeerStatus {
|
||||
loadedDocs: number;
|
||||
pendingPullUpdates: number;
|
||||
pendingPushUpdates: number;
|
||||
rootDocLoaded: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,6 +55,7 @@ export class SyncPeer {
|
||||
loadedDocs: 0,
|
||||
pendingPullUpdates: 0,
|
||||
pendingPushUpdates: 0,
|
||||
rootDocLoaded: false,
|
||||
};
|
||||
onStatusChange = new Slot<SyncPeerStatus>();
|
||||
readonly abort = new AbortController();
|
||||
@@ -119,6 +121,7 @@ export class SyncPeer {
|
||||
loadedDocs: 0,
|
||||
pendingPullUpdates: 0,
|
||||
pendingPushUpdates: 0,
|
||||
rootDocLoaded: this.status.rootDocLoaded,
|
||||
};
|
||||
await Promise.race([
|
||||
new Promise<void>(resolve => {
|
||||
@@ -291,6 +294,13 @@ export class SyncPeer {
|
||||
(await this.storage.pull(doc.guid, encodeStateVector(doc))) ?? {};
|
||||
throwIfAborted(abort);
|
||||
|
||||
if (docData !== undefined && doc.guid === this.rootDoc.guid) {
|
||||
this.status = {
|
||||
...this.status,
|
||||
rootDocLoaded: true,
|
||||
};
|
||||
}
|
||||
|
||||
if (docData) {
|
||||
applyUpdate(doc, docData, 'load');
|
||||
}
|
||||
@@ -391,6 +401,7 @@ export class SyncPeer {
|
||||
this.state.pullUpdatesQueue.length + (this.state.subdocLoading ? 1 : 0),
|
||||
pendingPushUpdates:
|
||||
this.state.pushUpdatesQueue.length + (this.state.pushingUpdate ? 1 : 0),
|
||||
rootDocLoaded: this.status.rootDocLoaded,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
workspaceListLoadingStatusAtom,
|
||||
workspaceManagerAtom,
|
||||
} from '@affine/core/modules/workspace';
|
||||
import { type Workspace } from '@affine/workspace';
|
||||
import type { Workspace } from '@affine/workspace';
|
||||
import { type SyncEngineStatus } from '@affine/workspace';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import {
|
||||
type ReactElement,
|
||||
@@ -75,25 +76,32 @@ export const Component = (): ReactElement => {
|
||||
|
||||
const [workspaceIsLoading, setWorkspaceIsLoading] = useState(true);
|
||||
|
||||
const [syncEngineStatus, setSyncEngineStatus] = useState<SyncEngineStatus>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!workspace) {
|
||||
setSyncEngineStatus(undefined);
|
||||
}
|
||||
return workspace?.engine.sync.onStatusChange.on(setSyncEngineStatus)
|
||||
.dispose;
|
||||
}, [workspace]);
|
||||
|
||||
// hotfix: avoid doing operation, before workspace is loaded
|
||||
useEffect(() => {
|
||||
if (!workspace) {
|
||||
setWorkspaceIsLoading(true);
|
||||
return;
|
||||
}
|
||||
const metaYMap = workspace.blockSuiteWorkspace.doc.getMap('meta');
|
||||
|
||||
const handleYMapChanged = () => {
|
||||
setWorkspaceIsLoading(metaYMap.size === 0);
|
||||
};
|
||||
|
||||
handleYMapChanged();
|
||||
|
||||
metaYMap.observe(handleYMapChanged);
|
||||
return () => {
|
||||
metaYMap.unobserve(handleYMapChanged);
|
||||
};
|
||||
}, [workspace]);
|
||||
if (
|
||||
[syncEngineStatus?.local, ...(syncEngineStatus?.remotes ?? [])].some(
|
||||
p => p?.rootDocLoaded === true
|
||||
)
|
||||
) {
|
||||
setWorkspaceIsLoading(false);
|
||||
} else {
|
||||
setWorkspaceIsLoading(true);
|
||||
}
|
||||
}, [syncEngineStatus, workspace]);
|
||||
|
||||
// if listLoading is false, we can show 404 page, otherwise we should show loading page.
|
||||
if (listLoading === false && meta === undefined) {
|
||||
|
||||
Reference in New Issue
Block a user