+
+ {t['com.affine.migration-all-docs-notification.title']()}
+
+
+ {t['com.affine.migration-all-docs-notification.content']()}
+
+
+ {error && (
+
+ {t['com.affine.migration-all-docs-notification.error']({
+ errorMessage: errorMessage ?? '',
+ })}
+
+ )}
+
+
+
+ );
+};
diff --git a/packages/frontend/core/src/modules/cloud/index.ts b/packages/frontend/core/src/modules/cloud/index.ts
index c5e48a8b2..89ec23d29 100644
--- a/packages/frontend/core/src/modules/cloud/index.ts
+++ b/packages/frontend/core/src/modules/cloud/index.ts
@@ -10,6 +10,7 @@ export { ServerScope } from './scopes/server';
export { AuthService } from './services/auth';
export { CaptchaService } from './services/captcha';
export { DefaultServerService } from './services/default-server';
+export { DocCreatedByUpdatedBySyncService } from './services/doc-created-by-updated-by-sync';
export { EventSourceService } from './services/eventsource';
export { FetchService } from './services/fetch';
export { GraphQLService } from './services/graphql';
@@ -98,6 +99,10 @@ import { UserQuotaStore } from './stores/user-quota';
import { UserSettingsStore } from './stores/user-settings';
import { DocCreatedByService } from './services/doc-created-by';
import { DocUpdatedByService } from './services/doc-updated-by';
+import { DocCreatedByUpdatedBySyncService } from './services/doc-created-by-updated-by-sync';
+import { WorkspacePermissionService } from '../permissions';
+import { DocsService } from '../doc';
+import { DocCreatedByUpdatedBySyncStore } from './stores/doc-created-by-updated-by-sync';
export function configureCloudModule(framework: Framework) {
configureDefaultAuthProvider(framework);
@@ -181,5 +186,15 @@ export function configureCloudModule(framework: Framework) {
.entity(WorkspaceInvoices, [WorkspaceService, WorkspaceServerService])
.service(SelfhostLicenseService, [SelfhostLicenseStore, WorkspaceService])
.store(SelfhostLicenseStore, [WorkspaceServerService])
- .service(BlocksuiteWriterInfoService, [WorkspaceServerService]);
+ .service(BlocksuiteWriterInfoService, [WorkspaceServerService])
+ .service(DocCreatedByUpdatedBySyncService, [
+ WorkspaceService,
+ DocsService,
+ WorkspacePermissionService,
+ DocCreatedByUpdatedBySyncStore,
+ ])
+ .store(DocCreatedByUpdatedBySyncStore, [
+ WorkspaceServerService,
+ WorkspaceService,
+ ]);
}
diff --git a/packages/frontend/core/src/modules/cloud/services/doc-created-by-updated-by-sync.ts b/packages/frontend/core/src/modules/cloud/services/doc-created-by-updated-by-sync.ts
new file mode 100644
index 000000000..9e8682b56
--- /dev/null
+++ b/packages/frontend/core/src/modules/cloud/services/doc-created-by-updated-by-sync.ts
@@ -0,0 +1,150 @@
+import {
+ catchErrorInto,
+ effect,
+ fromPromise,
+ LiveData,
+ onStart,
+ Service,
+ throwIfAborted,
+} from '@toeverything/infra';
+import { clamp } from 'lodash-es';
+import { combineLatest, exhaustMap, finalize, map } from 'rxjs';
+
+import type { DocsService } from '../../doc';
+import type { WorkspacePermissionService } from '../../permissions';
+import type { WorkspaceService } from '../../workspace';
+import type { DocCreatedByUpdatedBySyncStore } from '../stores/doc-created-by-updated-by-sync';
+
+/**
+ * This service is used to sync createdBy and updatedBy data from the cloud to local doc properties.
+ *
+ * # When sync is needed
+ *
+ * 1. When the user is an owner or admin
+ * 2. When the root doc sync is complete
+ * 3. When a doc is missing createdBy data
+ * 4. When workspace has not been marked as `DocCreatedByUpdatedBySynced`
+ */
+export class DocCreatedByUpdatedBySyncService extends Service {
+ constructor(
+ private readonly workspaceService: WorkspaceService,
+ private readonly docsService: DocsService,
+ private readonly workspacePermissionService: WorkspacePermissionService,
+ private readonly docCreatedByUpdatedBySyncStore: DocCreatedByUpdatedBySyncStore
+ ) {
+ super();
+ }
+
+ syncing$ = new LiveData(false);
+ error$ = new LiveData