feat: bump blocksuite (#6078)

This commit is contained in:
regischen
2024-03-13 17:04:21 +08:00
committed by GitHub
parent 573528be41
commit fddbb426a6
126 changed files with 891 additions and 918 deletions

View File

@@ -3,8 +3,8 @@
"private": true, "private": true,
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@blocksuite/global": "0.13.0-canary-202403050653-934469c", "@blocksuite/global": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"vitest": "1.3.1" "vitest": "1.3.1"

View File

@@ -1,5 +1,5 @@
// This file should has not side effect // This file should has not side effect
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
declare global { declare global {
interface Window { interface Window {
@@ -95,12 +95,12 @@ export const Messages = {
}; };
export class PageNotFoundError extends TypeError { export class PageNotFoundError extends TypeError {
readonly workspace: Workspace; readonly docCollection: DocCollection;
readonly pageId: string; readonly pageId: string;
constructor(workspace: Workspace, pageId: string) { constructor(docCollection: DocCollection, pageId: string) {
super(); super();
this.workspace = workspace; this.docCollection = docCollection;
this.pageId = pageId; this.pageId = pageId;
} }
} }

View File

@@ -1,4 +1,4 @@
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { z } from 'zod'; import { z } from 'zod';
export const literalValueSchema: z.ZodType<LiteralValue, z.ZodTypeDef> = export const literalValueSchema: z.ZodType<LiteralValue, z.ZodTypeDef> =
@@ -81,4 +81,4 @@ export const tagSchema = z.object({
}); });
export type Tag = z.input<typeof tagSchema>; export type Tag = z.input<typeof tagSchema>;
export type PropertiesMeta = Workspace['meta']['properties']; export type PropertiesMeta = DocCollection['meta']['properties'];

View File

@@ -1,6 +1,6 @@
/// <reference types="@blocksuite/global" /> /// <reference types="@blocksuite/global" />
import { assertEquals } from '@blocksuite/global/utils'; import { assertEquals } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { z } from 'zod'; import { z } from 'zod';
import { isDesktop, isServer } from './constant.js'; import { isDesktop, isServer } from './constant.js';
@@ -154,9 +154,9 @@ export function setupGlobal() {
globalThis.$AFFINE_SETUP = true; globalThis.$AFFINE_SETUP = true;
} }
export function setupEditorFlags(workspace: Workspace) { export function setupEditorFlags(docCollection: DocCollection) {
Object.entries(runtimeConfig.editorFlags).forEach(([key, value]) => { Object.entries(runtimeConfig.editorFlags).forEach(([key, value]) => {
workspace.awarenessStore.setFlag( docCollection.awarenessStore.setFlag(
key as keyof BlockSuiteFeatureFlags, key as keyof BlockSuiteFeatureFlags,
value value
); );

View File

@@ -17,9 +17,9 @@
"@affine/debug": "workspace:*", "@affine/debug": "workspace:*",
"@affine/env": "workspace:*", "@affine/env": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@blocksuite/blocks": "0.13.0-canary-202403050653-934469c", "@blocksuite/blocks": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/global": "0.13.0-canary-202403050653-934469c", "@blocksuite/global": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"foxact": "^0.2.31", "foxact": "^0.2.31",
"jotai": "^2.6.5", "jotai": "^2.6.5",
"jotai-effect": "^0.6.0", "jotai-effect": "^0.6.0",
@@ -33,8 +33,8 @@
"devDependencies": { "devDependencies": {
"@affine-test/fixtures": "workspace:*", "@affine-test/fixtures": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@blocksuite/lit": "0.13.0-canary-202403050653-934469c", "@blocksuite/lit": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/presets": "0.13.0-canary-202403050653-934469c", "@blocksuite/presets": "0.13.0-canary-202403120738-e15d583",
"@testing-library/react": "^14.2.1", "@testing-library/react": "^14.2.1",
"async-call-rpc": "^6.4.0", "async-call-rpc": "^6.4.0",
"react": "^18.2.0", "react": "^18.2.0",

View File

@@ -35,7 +35,7 @@ export async function migratePages(
console.error(e); console.error(e);
} }
}); });
schema.upgradeWorkspace(rootDoc); schema.upgradeCollection(rootDoc);
// Hard code to upgrade page version to 2. // Hard code to upgrade page version to 2.
// Let e2e to ensure the data version is correct. // Let e2e to ensure the data version is correct.

View File

@@ -1,4 +1,4 @@
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { Array as YArray, Doc as YDoc, Map as YMap } from 'yjs'; import type { Array as YArray, Doc as YDoc, Map as YMap } from 'yjs';
/** /**
@@ -11,14 +11,14 @@ export enum MigrationPoint {
} }
export function checkWorkspaceCompatibility( export function checkWorkspaceCompatibility(
workspace: Workspace, docCollection: DocCollection,
isCloud: boolean isCloud: boolean
): MigrationPoint | null { ): MigrationPoint | null {
// check if there is any key starts with 'space:' on root doc // check if there is any key starts with 'space:' on root doc
const spaceMetaObj = workspace.doc.share.get('space:meta') as const spaceMetaObj = docCollection.doc.share.get('space:meta') as
| YMap<any> | YMap<any>
| undefined; | undefined;
const docKeys = Array.from(workspace.doc.share.keys()); const docKeys = Array.from(docCollection.doc.share.keys());
const haveSpaceMeta = !!spaceMetaObj && spaceMetaObj.size > 0; const haveSpaceMeta = !!spaceMetaObj && spaceMetaObj.size > 0;
const haveLegacySpace = docKeys.some(key => key.startsWith('space:')); const haveLegacySpace = docKeys.some(key => key.startsWith('space:'));
@@ -28,12 +28,12 @@ export function checkWorkspaceCompatibility(
} }
// exit if no pages // exit if no pages
if (!workspace.meta.docs?.length) { if (!docCollection.meta.docs?.length) {
return null; return null;
} }
// check guid compatibility // check guid compatibility
const meta = workspace.doc.getMap('meta') as YMap<unknown>; const meta = docCollection.doc.getMap('meta') as YMap<unknown>;
const pages = meta.get('pages') as YArray<YMap<unknown>>; const pages = meta.get('pages') as YArray<YMap<unknown>>;
for (const page of pages) { for (const page of pages) {
const pageId = page.get('id') as string | undefined; const pageId = page.get('id') as string | undefined;
@@ -41,23 +41,23 @@ export function checkWorkspaceCompatibility(
return MigrationPoint.GuidFix; return MigrationPoint.GuidFix;
} }
} }
const spaces = workspace.doc.getMap('spaces') as YMap<YDoc>; const spaces = docCollection.doc.getMap('spaces') as YMap<YDoc>;
for (const [pageId, _] of spaces) { for (const [pageId, _] of spaces) {
if (pageId.includes(':')) { if (pageId.includes(':')) {
return MigrationPoint.GuidFix; return MigrationPoint.GuidFix;
} }
} }
const hasVersion = workspace.meta.hasVersion; const hasVersion = docCollection.meta.hasVersion;
if (!hasVersion) { if (!hasVersion) {
return MigrationPoint.BlockVersion; return MigrationPoint.BlockVersion;
} }
// TODO: Catch compatibility error from blocksuite to show upgrade page. // TODO: Catch compatibility error from blocksuite to show upgrade page.
// Temporarily follow the check logic of blocksuite. // Temporarily follow the check logic of blocksuite.
if ((workspace.meta.docs?.length ?? 0) <= 1) { if ((docCollection.meta.docs?.length ?? 0) <= 1) {
try { try {
workspace.meta.validateVersion(workspace); docCollection.meta.validateVersion(docCollection);
} catch (e) { } catch (e) {
console.info('validateVersion error', e); console.info('validateVersion error', e);
return MigrationPoint.BlockVersion; return MigrationPoint.BlockVersion;
@@ -65,9 +65,9 @@ export function checkWorkspaceCompatibility(
} }
// From v2, we depend on blocksuite to check and migrate data. // From v2, we depend on blocksuite to check and migrate data.
const blockVersions = workspace.meta.blockVersions; const blockVersions = docCollection.meta.blockVersions;
for (const [flavour, version] of Object.entries(blockVersions ?? {})) { for (const [flavour, version] of Object.entries(blockVersions ?? {})) {
const schema = workspace.schema.flavourSchemaMap.get(flavour); const schema = docCollection.schema.flavourSchemaMap.get(flavour);
if (schema?.version !== version) { if (schema?.version !== version) {
return MigrationPoint.BlockVersion; return MigrationPoint.BlockVersion;
} }

View File

@@ -1,9 +1,9 @@
import type { WorkspaceFlavour } from '@affine/env/workspace'; import type { WorkspaceFlavour } from '@affine/env/workspace';
import type { import type {
CollectionInfoSnapshot,
Doc, Doc,
DocSnapshot, DocSnapshot,
JobMiddleware, JobMiddleware,
WorkspaceInfoSnapshot,
} from '@blocksuite/store'; } from '@blocksuite/store';
import { Job } from '@blocksuite/store'; import { Job } from '@blocksuite/store';
import { Map as YMap } from 'yjs'; import { Map as YMap } from 'yjs';
@@ -49,17 +49,17 @@ export async function buildShowcaseWorkspace(
) { ) {
const meta = await workspaceManager.createWorkspace( const meta = await workspaceManager.createWorkspace(
flavour, flavour,
async (blockSuiteWorkspace, blobStorage) => { async (docCollection, blobStorage) => {
blockSuiteWorkspace.meta.setName(workspaceName); docCollection.meta.setName(workspaceName);
const { onboarding } = await import('@affine/templates'); const { onboarding } = await import('@affine/templates');
const info = onboarding['info.json'] as WorkspaceInfoSnapshot; const info = onboarding['info.json'] as CollectionInfoSnapshot;
const blob = onboarding['blob.json'] as { [key: string]: string }; const blob = onboarding['blob.json'] as { [key: string]: string };
const migrationMiddleware: JobMiddleware = ({ slots, workspace }) => { const migrationMiddleware: JobMiddleware = ({ slots, collection }) => {
slots.afterImport.on(payload => { slots.afterImport.on(payload => {
if (payload.type === 'page') { if (payload.type === 'page') {
workspace.schema.upgradeDoc( collection.schema.upgradeDoc(
info?.pageVersion ?? 0, info?.pageVersion ?? 0,
{}, {},
payload.page.spaceDoc payload.page.spaceDoc
@@ -69,11 +69,11 @@ export async function buildShowcaseWorkspace(
}; };
const job = new Job({ const job = new Job({
workspace: blockSuiteWorkspace, collection: docCollection,
middlewares: [replaceIdMiddleware, migrationMiddleware], middlewares: [replaceIdMiddleware, migrationMiddleware],
}); });
job.snapshotToWorkspaceInfo(info); job.snapshotToCollectionInfo(info);
// for now all onboarding assets are considered served via CDN // for now all onboarding assets are considered served via CDN
// hack assets so that every blob exists // hack assets so that every blob exists
@@ -92,8 +92,8 @@ export async function buildShowcaseWorkspace(
}) })
); );
const newVersions = getLatestVersions(blockSuiteWorkspace.schema); const newVersions = getLatestVersions(docCollection.schema);
blockSuiteWorkspace.doc docCollection.doc
.getMap('meta') .getMap('meta')
.set('blockVersions', new YMap(Object.entries(newVersions))); .set('blockVersions', new YMap(Object.entries(newVersions)));

View File

@@ -20,7 +20,7 @@ export class PageManager {
if (!pageRecord) { if (!pageRecord) {
throw new Error('Page record not found'); throw new Error('Page record not found');
} }
const blockSuitePage = this.workspace.blockSuiteWorkspace.getDoc(pageId); const blockSuitePage = this.workspace.docCollection.getDoc(pageId);
if (!blockSuitePage) { if (!blockSuitePage) {
throw new Error('Page not found'); throw new Error('Page not found');
} }

View File

@@ -18,7 +18,7 @@ export class PageRecordList {
new Observable(subscriber => { new Observable(subscriber => {
const emit = () => { const emit = () => {
subscriber.next( subscriber.next(
this.workspace.blockSuiteWorkspace.meta.docMetas.map( this.workspace.docCollection.meta.docMetas.map(
v => new PageRecord(v.id, this.workspace, this.localState) v => new PageRecord(v.id, this.workspace, this.localState)
) )
); );
@@ -27,7 +27,7 @@ export class PageRecordList {
emit(); emit();
const dispose = const dispose =
this.workspace.blockSuiteWorkspace.meta.docMetaUpdated.on(emit).dispose; this.workspace.docCollection.meta.docMetaUpdated.on(emit).dispose;
return () => { return () => {
dispose(); dispose();
}; };

View File

@@ -16,7 +16,7 @@ export class PageRecord {
meta = LiveData.from<DocMeta>( meta = LiveData.from<DocMeta>(
new Observable(subscriber => { new Observable(subscriber => {
const emit = () => { const emit = () => {
const meta = this.workspace.blockSuiteWorkspace.meta.docMetas.find( const meta = this.workspace.docCollection.meta.docMetas.find(
page => page.id === this.id page => page.id === this.id
); );
if (meta === undefined) { if (meta === undefined) {
@@ -28,7 +28,7 @@ export class PageRecord {
emit(); emit();
const dispose = const dispose =
this.workspace.blockSuiteWorkspace.meta.docMetaUpdated.on(emit).dispose; this.workspace.docCollection.meta.docMetaUpdated.on(emit).dispose;
return () => { return () => {
dispose(); dispose();
}; };
@@ -42,7 +42,7 @@ export class PageRecord {
); );
setMeta(meta: Partial<DocMeta>): void { setMeta(meta: Partial<DocMeta>): void {
this.workspace.blockSuiteWorkspace.setDocMeta(this.id, meta); this.workspace.docCollection.setDocMeta(this.id, meta);
} }
mode: LiveData<PageMode> = LiveData.from( mode: LiveData<PageMode> = LiveData.from(

View File

@@ -22,7 +22,7 @@ describe('Workspace System', () => {
expect(workspaceListService.workspaceList.value.length).toBe(1); expect(workspaceListService.workspaceList.value.length).toBe(1);
const page = workspace.blockSuiteWorkspace.createDoc({ const page = workspace.docCollection.createDoc({
id: 'page0', id: 'page0',
}); });
page.load(); page.load();
@@ -30,7 +30,7 @@ describe('Workspace System', () => {
title: new page.Text('test-page'), title: new page.Text('test-page'),
}); });
expect(workspace.blockSuiteWorkspace.docs.size).toBe(1); expect(workspace.docCollection.docs.size).toBe(1);
expect( expect(
(page!.getBlockByFlavour('affine:page')[0] as any).title.toString() (page!.getBlockByFlavour('affine:page')[0] as any).title.toString()
).toBe('test-page'); ).toBe('test-page');

View File

@@ -18,7 +18,7 @@
* }) * })
*/ */
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import { DocCollection } from '@blocksuite/store';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import type { Awareness } from 'y-protocols/awareness.js'; import type { Awareness } from 'y-protocols/awareness.js';
import type { Doc as YDoc } from 'yjs'; import type { Doc as YDoc } from 'yjs';
@@ -29,7 +29,7 @@ import { globalBlockSuiteSchema } from './global-schema';
import type { WorkspaceMetadata } from './metadata'; import type { WorkspaceMetadata } from './metadata';
import { WorkspaceScope } from './service-scope'; import { WorkspaceScope } from './service-scope';
export const BlockSuiteWorkspaceContext = createIdentifier<BlockSuiteWorkspace>( export const BlockSuiteWorkspaceContext = createIdentifier<DocCollection>(
'BlockSuiteWorkspaceContext' 'BlockSuiteWorkspaceContext'
); );
@@ -53,7 +53,7 @@ export function configureWorkspaceContext(
.addImpl(WorkspaceMetadataContext, workspaceMetadata) .addImpl(WorkspaceMetadataContext, workspaceMetadata)
.addImpl(WorkspaceIdContext, workspaceMetadata.id) .addImpl(WorkspaceIdContext, workspaceMetadata.id)
.addImpl(BlockSuiteWorkspaceContext, provider => { .addImpl(BlockSuiteWorkspaceContext, provider => {
return new BlockSuiteWorkspace({ return new DocCollection({
id: workspaceMetadata.id, id: workspaceMetadata.id,
blobStorages: [ blobStorages: [
() => ({ () => ({

View File

@@ -1,5 +1,5 @@
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { Workspace } from '@blocksuite/store'; import { DocCollection } from '@blocksuite/store';
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
import { Doc } from 'yjs'; import { Doc } from 'yjs';
@@ -26,14 +26,14 @@ describe('SyncEngine', () => {
const storage2 = new MemoryMemento(); const storage2 = new MemoryMemento();
let prev: any; let prev: any;
{ {
const workspace = new Workspace({ const docCollection = new DocCollection({
id: 'test', id: 'test',
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
const syncEngine = new SyncEngine( const syncEngine = new SyncEngine(
workspace.doc, docCollection.doc,
new TestingSyncStorage(testMeta, storage), new TestingSyncStorage(testMeta, storage),
[ [
new TestingSyncStorage(testMeta, storage1), new TestingSyncStorage(testMeta, storage1),
@@ -42,7 +42,7 @@ describe('SyncEngine', () => {
); );
syncEngine.start(); syncEngine.start();
const page = workspace.createDoc({ const page = docCollection.createDoc({
id: 'page0', id: 'page0',
}); });
page.load(); page.load();
@@ -69,23 +69,23 @@ describe('SyncEngine', () => {
); );
await syncEngine.waitForSynced(); await syncEngine.waitForSynced();
syncEngine.forceStop(); syncEngine.forceStop();
prev = workspace.doc.toJSON(); prev = docCollection.doc.toJSON();
} }
for (const current of [storage, storage1, storage2]) { for (const current of [storage, storage1, storage2]) {
const workspace = new Workspace({ const docCollection = new DocCollection({
id: 'test', id: 'test',
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
const syncEngine = new SyncEngine( const syncEngine = new SyncEngine(
workspace.doc, docCollection.doc,
new TestingSyncStorage(testMeta, current), new TestingSyncStorage(testMeta, current),
[] []
); );
syncEngine.start(); syncEngine.start();
await syncEngine.waitForSynced(); await syncEngine.waitForSynced();
expect(workspace.doc.toJSON()).toEqual({ expect(docCollection.doc.toJSON()).toEqual({
...prev, ...prev,
}); });
syncEngine.forceStop(); syncEngine.forceStop();

View File

@@ -1,5 +1,5 @@
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { Workspace } from '@blocksuite/store'; import { DocCollection } from '@blocksuite/store';
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
import { MemoryMemento } from '../../../../storage'; import { MemoryMemento } from '../../../../storage';
@@ -23,19 +23,19 @@ describe('SyncPeer', () => {
let prev: any; let prev: any;
{ {
const workspace = new Workspace({ const docCollection = new DocCollection({
id: 'test', id: 'test',
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
const syncPeer = new SyncPeer( const syncPeer = new SyncPeer(
workspace.doc, docCollection.doc,
new TestingSyncStorage(testMeta, storage) new TestingSyncStorage(testMeta, storage)
); );
await syncPeer.waitForLoaded(); await syncPeer.waitForLoaded();
const page = workspace.createDoc({ const page = docCollection.createDoc({
id: 'page0', id: 'page0',
}); });
page.load(); page.load();
@@ -62,21 +62,21 @@ describe('SyncPeer', () => {
); );
await syncPeer.waitForSynced(); await syncPeer.waitForSynced();
syncPeer.stop(); syncPeer.stop();
prev = workspace.doc.toJSON(); prev = docCollection.doc.toJSON();
} }
{ {
const workspace = new Workspace({ const docCollection = new DocCollection({
id: 'test', id: 'test',
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
const syncPeer = new SyncPeer( const syncPeer = new SyncPeer(
workspace.doc, docCollection.doc,
new TestingSyncStorage(testMeta, storage) new TestingSyncStorage(testMeta, storage)
); );
await syncPeer.waitForSynced(); await syncPeer.waitForSynced();
expect(workspace.doc.toJSON()).toEqual({ expect(docCollection.doc.toJSON()).toEqual({
...prev, ...prev,
}); });
syncPeer.stop(); syncPeer.stop();
@@ -86,21 +86,21 @@ describe('SyncPeer', () => {
test('status', async () => { test('status', async () => {
const storage = new MemoryMemento(); const storage = new MemoryMemento();
const workspace = new Workspace({ const docCollection = new DocCollection({
id: 'test', id: 'test',
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
const syncPeer = new SyncPeer( const syncPeer = new SyncPeer(
workspace.doc, docCollection.doc,
new TestingSyncStorage(testMeta, storage) new TestingSyncStorage(testMeta, storage)
); );
expect(syncPeer.status.step).toBe(SyncPeerStep.LoadingRootDoc); expect(syncPeer.status.step).toBe(SyncPeerStep.LoadingRootDoc);
await syncPeer.waitForSynced(); await syncPeer.waitForSynced();
expect(syncPeer.status.step).toBe(SyncPeerStep.Synced); expect(syncPeer.status.step).toBe(SyncPeerStep.Synced);
const page = workspace.createDoc({ const page = docCollection.createDoc({
id: 'page0', id: 'page0',
}); });
expect(syncPeer.status.step).toBe(SyncPeerStep.LoadingSubDoc); expect(syncPeer.status.step).toBe(SyncPeerStep.LoadingSubDoc);

View File

@@ -1,6 +1,6 @@
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import type { WorkspaceFlavour } from '@affine/env/workspace'; import type { WorkspaceFlavour } from '@affine/env/workspace';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { differenceWith } from 'lodash-es'; import { differenceWith } from 'lodash-es';
import { createIdentifier } from '../../di'; import { createIdentifier } from '../../di';
@@ -34,7 +34,7 @@ export interface WorkspaceListProvider {
*/ */
create( create(
initial: ( initial: (
workspace: BlockSuiteWorkspace, docCollection: DocCollection,
blobStorage: BlobStorage blobStorage: BlobStorage
) => Promise<void> ) => Promise<void>
): Promise<WorkspaceMetadata>; ): Promise<WorkspaceMetadata>;
@@ -124,7 +124,7 @@ export class WorkspaceListService {
async create( async create(
flavour: WorkspaceFlavour, flavour: WorkspaceFlavour,
initial: ( initial: (
workspace: BlockSuiteWorkspace, docCollection: DocCollection,
blobStorage: BlobStorage blobStorage: BlobStorage
) => Promise<void> = () => Promise.resolve() ) => Promise<void> = () => Promise.resolve()
) { ) {

View File

@@ -57,13 +57,13 @@ export class WorkspaceInformation {
*/ */
syncWithWorkspace(workspace: Workspace) { syncWithWorkspace(workspace: Workspace) {
this.info = { this.info = {
avatar: workspace.blockSuiteWorkspace.meta.avatar ?? this.info.avatar, avatar: workspace.docCollection.meta.avatar ?? this.info.avatar,
name: workspace.blockSuiteWorkspace.meta.name ?? this.info.name, name: workspace.docCollection.meta.name ?? this.info.name,
}; };
workspace.blockSuiteWorkspace.meta.commonFieldsUpdated.on(() => { workspace.docCollection.meta.commonFieldsUpdated.on(() => {
this.info = { this.info = {
avatar: workspace.blockSuiteWorkspace.meta.avatar ?? this.info.avatar, avatar: workspace.docCollection.meta.avatar ?? this.info.avatar,
name: workspace.blockSuiteWorkspace.meta.name ?? this.info.name, name: workspace.docCollection.meta.name ?? this.info.name,
}; };
}); });
} }

View File

@@ -2,7 +2,7 @@ import { DebugLogger } from '@affine/debug';
import { setupEditorFlags } from '@affine/env/global'; import { setupEditorFlags } from '@affine/env/global';
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { assertEquals } from '@blocksuite/global/utils'; import { assertEquals } from '@blocksuite/global/utils';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { applyUpdate, encodeStateAsUpdate } from 'yjs'; import { applyUpdate, encodeStateAsUpdate } from 'yjs';
import { fixWorkspaceVersion } from '../blocksuite'; import { fixWorkspaceVersion } from '../blocksuite';
@@ -105,7 +105,7 @@ export class WorkspaceManager {
createWorkspace( createWorkspace(
flavour: WorkspaceFlavour, flavour: WorkspaceFlavour,
initial?: ( initial?: (
workspace: BlockSuiteWorkspace, docCollection: DocCollection,
blobStorage: BlobStorage blobStorage: BlobStorage
) => Promise<void> ) => Promise<void>
): Promise<WorkspaceMetadata> { ): Promise<WorkspaceMetadata> {
@@ -131,9 +131,9 @@ export class WorkspaceManager {
const newId = await this.list.create( const newId = await this.list.create(
WorkspaceFlavour.AFFINE_CLOUD, WorkspaceFlavour.AFFINE_CLOUD,
async (ws, bs) => { async (ws, bs) => {
applyUpdate(ws.doc, encodeStateAsUpdate(local.blockSuiteWorkspace.doc)); applyUpdate(ws.doc, encodeStateAsUpdate(local.docCollection.doc));
for (const subdoc of local.blockSuiteWorkspace.doc.getSubdocs()) { for (const subdoc of local.docCollection.doc.getSubdocs()) {
for (const newSubdoc of ws.doc.getSubdocs()) { for (const newSubdoc of ws.doc.getSubdocs()) {
if (newSubdoc.guid === subdoc.guid) { if (newSubdoc.guid === subdoc.guid) {
applyUpdate(newSubdoc, encodeStateAsUpdate(subdoc)); applyUpdate(newSubdoc, encodeStateAsUpdate(subdoc));
@@ -191,9 +191,9 @@ export class WorkspaceManager {
const workspace = provider.get(Workspace); const workspace = provider.get(Workspace);
// apply compatibility fix // apply compatibility fix
fixWorkspaceVersion(workspace.blockSuiteWorkspace.doc); fixWorkspaceVersion(workspace.docCollection.doc);
setupEditorFlags(workspace.blockSuiteWorkspace); setupEditorFlags(workspace.docCollection);
return workspace; return workspace;
} }

View File

@@ -1,5 +1,5 @@
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import { DocCollection } from '@blocksuite/store';
import { differenceBy } from 'lodash-es'; import { differenceBy } from 'lodash-es';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { applyUpdate, encodeStateAsUpdate } from 'yjs'; import { applyUpdate, encodeStateAsUpdate } from 'yjs';
@@ -43,7 +43,7 @@ export class TestingLocalWorkspaceListProvider
} }
async create( async create(
initial: ( initial: (
workspace: BlockSuiteWorkspace, docCollection: DocCollection,
blobStorage: BlobStorage blobStorage: BlobStorage
) => Promise<void> ) => Promise<void>
): Promise<WorkspaceMetadata> { ): Promise<WorkspaceMetadata> {
@@ -53,18 +53,18 @@ export class TestingLocalWorkspaceListProvider
const blobStorage = new TestingBlobStorage(meta, this.state); const blobStorage = new TestingBlobStorage(meta, this.state);
const syncStorage = new TestingSyncStorage(meta, this.state); const syncStorage = new TestingSyncStorage(meta, this.state);
const workspace = new BlockSuiteWorkspace({ const docCollection = new DocCollection({
id: id, id: id,
idGenerator: () => nanoid(), idGenerator: () => nanoid(),
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
// apply initial state // apply initial state
await initial(workspace, blobStorage); await initial(docCollection, blobStorage);
// save workspace to storage // save workspace to storage
await syncStorage.push(id, encodeStateAsUpdate(workspace.doc)); await syncStorage.push(id, encodeStateAsUpdate(docCollection.doc));
for (const subdocs of workspace.doc.getSubdocs()) { for (const subdocs of docCollection.doc.getSubdocs()) {
await syncStorage.push(subdocs.guid, encodeStateAsUpdate(subdocs)); await syncStorage.push(subdocs.guid, encodeStateAsUpdate(subdocs));
} }
@@ -117,7 +117,7 @@ export class TestingLocalWorkspaceListProvider
return; return;
} }
const bs = new BlockSuiteWorkspace({ const bs = new DocCollection({
id, id,
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });

View File

@@ -1,7 +1,7 @@
import { Unreachable } from '@affine/env/constant'; import { Unreachable } from '@affine/env/constant';
import { WorkspaceFlavour } from '@affine/env/workspace'; import { WorkspaceFlavour } from '@affine/env/workspace';
import { Slot } from '@blocksuite/global/utils'; import { Slot } from '@blocksuite/global/utils';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { applyUpdate, Doc as YDoc, encodeStateAsUpdate } from 'yjs'; import { applyUpdate, Doc as YDoc, encodeStateAsUpdate } from 'yjs';
import { checkWorkspaceCompatibility, MigrationPoint } from '../blocksuite'; import { checkWorkspaceCompatibility, MigrationPoint } from '../blocksuite';
@@ -38,18 +38,18 @@ export class WorkspaceUpgradeController {
} }
constructor( constructor(
private readonly blockSuiteWorkspace: BlockSuiteWorkspace, private readonly docCollection: DocCollection,
private readonly sync: SyncEngine, private readonly sync: SyncEngine,
private readonly workspaceMetadata: WorkspaceMetadata private readonly workspaceMetadata: WorkspaceMetadata
) { ) {
blockSuiteWorkspace.doc.on('update', () => { docCollection.doc.on('update', () => {
this.checkIfNeedUpgrade(); this.checkIfNeedUpgrade();
}); });
} }
checkIfNeedUpgrade() { checkIfNeedUpgrade() {
const needUpgrade = !!checkWorkspaceCompatibility( const needUpgrade = !!checkWorkspaceCompatibility(
this.blockSuiteWorkspace, this.docCollection,
this.workspaceMetadata.flavour === WorkspaceFlavour.AFFINE_CLOUD this.workspaceMetadata.flavour === WorkspaceFlavour.AFFINE_CLOUD
); );
this.status = { this.status = {
@@ -72,7 +72,7 @@ export class WorkspaceUpgradeController {
await this.sync.waitForSynced(); await this.sync.waitForSynced();
const step = checkWorkspaceCompatibility( const step = checkWorkspaceCompatibility(
this.blockSuiteWorkspace, this.docCollection,
this.workspaceMetadata.flavour === WorkspaceFlavour.AFFINE_CLOUD this.workspaceMetadata.flavour === WorkspaceFlavour.AFFINE_CLOUD
); );
@@ -82,9 +82,9 @@ export class WorkspaceUpgradeController {
// Clone a new doc to prevent change events. // Clone a new doc to prevent change events.
const clonedDoc = new YDoc({ const clonedDoc = new YDoc({
guid: this.blockSuiteWorkspace.doc.guid, guid: this.docCollection.doc.guid,
}); });
applyDoc(clonedDoc, this.blockSuiteWorkspace.doc); applyDoc(clonedDoc, this.docCollection.doc);
if (step === MigrationPoint.SubDoc) { if (step === MigrationPoint.SubDoc) {
const newWorkspace = await workspaceManager.createWorkspace( const newWorkspace = await workspaceManager.createWorkspace(
@@ -92,14 +92,11 @@ export class WorkspaceUpgradeController {
async (workspace, blobStorage) => { async (workspace, blobStorage) => {
await upgradeV1ToV2(clonedDoc, workspace.doc); await upgradeV1ToV2(clonedDoc, workspace.doc);
migrateGuidCompatibility(clonedDoc); migrateGuidCompatibility(clonedDoc);
await forceUpgradePages( await forceUpgradePages(workspace.doc, this.docCollection.schema);
workspace.doc, const blobList = await this.docCollection.blob.list();
this.blockSuiteWorkspace.schema
);
const blobList = await this.blockSuiteWorkspace.blob.list();
for (const blobKey of blobList) { for (const blobKey of blobList) {
const blob = await this.blockSuiteWorkspace.blob.get(blobKey); const blob = await this.docCollection.blob.get(blobKey);
if (blob) { if (blob) {
await blobStorage.set(blobKey, blob); await blobStorage.set(blobKey, blob);
} }
@@ -110,13 +107,13 @@ export class WorkspaceUpgradeController {
return newWorkspace; return newWorkspace;
} else if (step === MigrationPoint.GuidFix) { } else if (step === MigrationPoint.GuidFix) {
migrateGuidCompatibility(clonedDoc); migrateGuidCompatibility(clonedDoc);
await forceUpgradePages(clonedDoc, this.blockSuiteWorkspace.schema); await forceUpgradePages(clonedDoc, this.docCollection.schema);
applyDoc(this.blockSuiteWorkspace.doc, clonedDoc); applyDoc(this.docCollection.doc, clonedDoc);
await this.sync.waitForSynced(); await this.sync.waitForSynced();
return null; return null;
} else if (step === MigrationPoint.BlockVersion) { } else if (step === MigrationPoint.BlockVersion) {
await forceUpgradePages(clonedDoc, this.blockSuiteWorkspace.schema); await forceUpgradePages(clonedDoc, this.docCollection.schema);
applyDoc(this.blockSuiteWorkspace.doc, clonedDoc); applyDoc(this.docCollection.doc, clonedDoc);
await this.sync.waitForSynced(); await this.sync.waitForSynced();
return null; return null;
} else { } else {

View File

@@ -1,6 +1,6 @@
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import { Slot } from '@blocksuite/global/utils'; import { Slot } from '@blocksuite/global/utils';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { ServiceProvider } from '../di'; import type { ServiceProvider } from '../di';
import { CleanupService } from '../lifecycle'; import { CleanupService } from '../lifecycle';
@@ -10,7 +10,7 @@ import { type WorkspaceMetadata } from './metadata';
import type { WorkspaceUpgradeController } from './upgrade'; import type { WorkspaceUpgradeController } from './upgrade';
import { type WorkspaceUpgradeStatus } from './upgrade'; import { type WorkspaceUpgradeStatus } from './upgrade';
export type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; export type { DocCollection } from '@blocksuite/store';
const logger = new DebugLogger('affine:workspace'); const logger = new DebugLogger('affine:workspace');
@@ -67,7 +67,7 @@ export class Workspace {
constructor( constructor(
public meta: WorkspaceMetadata, public meta: WorkspaceMetadata,
public engine: WorkspaceEngine, public engine: WorkspaceEngine,
public blockSuiteWorkspace: BlockSuiteWorkspace, public docCollection: DocCollection,
public upgrade: WorkspaceUpgradeController, public upgrade: WorkspaceUpgradeController,
public services: ServiceProvider public services: ServiceProvider
) { ) {

View File

@@ -32,14 +32,14 @@
} }
}, },
"dependencies": { "dependencies": {
"@blocksuite/global": "0.13.0-canary-202403050653-934469c", "@blocksuite/global": "0.13.0-canary-202403120738-e15d583",
"idb": "^8.0.0", "idb": "^8.0.0",
"nanoid": "^5.0.6", "nanoid": "^5.0.6",
"y-provider": "workspace:*" "y-provider": "workspace:*"
}, },
"devDependencies": { "devDependencies": {
"@blocksuite/blocks": "0.13.0-canary-202403050653-934469c", "@blocksuite/blocks": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"fake-indexeddb": "^5.0.2", "fake-indexeddb": "^5.0.2",
"vite": "^5.1.4", "vite": "^5.1.4",
"vite-plugin-dts": "3.7.3", "vite-plugin-dts": "3.7.3",

View File

@@ -8,7 +8,7 @@ import { setTimeout } from 'node:timers/promises';
import { AffineSchemas } from '@blocksuite/blocks/schemas'; import { AffineSchemas } from '@blocksuite/blocks/schemas';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import { Schema, Workspace } from '@blocksuite/store'; import { DocCollection, Schema } from '@blocksuite/store';
import { openDB } from 'idb'; import { openDB } from 'idb';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
@@ -69,7 +69,7 @@ async function getUpdates(id: string): Promise<Uint8Array[]> {
} }
let id: string; let id: string;
let workspace: Workspace; let docCollection: DocCollection;
const rootDBName = DEFAULT_DB_NAME; const rootDBName = DEFAULT_DB_NAME;
const schema = new Schema(); const schema = new Schema();
@@ -78,7 +78,7 @@ schema.register(AffineSchemas);
beforeEach(() => { beforeEach(() => {
id = nanoid(); id = nanoid();
workspace = new Workspace({ docCollection = new DocCollection({
id, id,
schema, schema,
@@ -93,7 +93,7 @@ afterEach(() => {
describe('indexeddb provider', () => { describe('indexeddb provider', () => {
test('connect', async () => { test('connect', async () => {
const provider = createIndexedDBProvider(workspace.doc); const provider = createIndexedDBProvider(docCollection.doc);
provider.connect(); provider.connect();
// todo: has a better way to know when data is synced // todo: has a better way to know when data is synced
@@ -110,11 +110,11 @@ describe('indexeddb provider', () => {
updates: [ updates: [
{ {
timestamp: expect.any(Number), timestamp: expect.any(Number),
update: encodeStateAsUpdate(workspace.doc), update: encodeStateAsUpdate(docCollection.doc),
}, },
], ],
}); });
const page = workspace.createDoc({ id: 'page0' }); const page = docCollection.createDoc({ id: 'page0' });
page.load(); page.load();
const pageBlockId = page.addBlock( const pageBlockId = page.addBlock(
'affine:page' as keyof BlockSuite.BlockModels, 'affine:page' as keyof BlockSuite.BlockModels,
@@ -139,13 +139,13 @@ describe('indexeddb provider', () => {
const data = (await store.get(id)) as WorkspacePersist | undefined; const data = (await store.get(id)) as WorkspacePersist | undefined;
assertExists(data); assertExists(data);
expect(data.id).toBe(id); expect(data.id).toBe(id);
const testWorkspace = new Workspace({ const testWorkspace = new DocCollection({
id: 'test', id: 'test',
schema, schema,
}); });
// data should only contain updates for the root doc // data should only contain updates for the root doc
data.updates.forEach(({ update }) => { data.updates.forEach(({ update }) => {
Workspace.Y.applyUpdate(testWorkspace.doc, update); DocCollection.Y.applyUpdate(testWorkspace.doc, update);
}); });
const subPage = testWorkspace.doc.spaces.get('page0'); const subPage = testWorkspace.doc.spaces.get('page0');
{ {
@@ -157,23 +157,23 @@ describe('indexeddb provider', () => {
assertExists(data); assertExists(data);
testWorkspace.getDoc('page0')?.load(); testWorkspace.getDoc('page0')?.load();
data.updates.forEach(({ update }) => { data.updates.forEach(({ update }) => {
Workspace.Y.applyUpdate(subPage, update); DocCollection.Y.applyUpdate(subPage, update);
}); });
} }
expect(workspace.doc.toJSON()).toEqual(testWorkspace.doc.toJSON()); expect(docCollection.doc.toJSON()).toEqual(testWorkspace.doc.toJSON());
} }
}); });
test('connect and disconnect', async () => { test('connect and disconnect', async () => {
const provider = createIndexedDBProvider(workspace.doc, rootDBName); const provider = createIndexedDBProvider(docCollection.doc, rootDBName);
provider.connect(); provider.connect();
expect(provider.connected).toBe(true); expect(provider.connected).toBe(true);
await setTimeout(200); await setTimeout(200);
const snapshot = encodeStateAsUpdate(workspace.doc); const snapshot = encodeStateAsUpdate(docCollection.doc);
provider.disconnect(); provider.disconnect();
expect(provider.connected).toBe(false); expect(provider.connected).toBe(false);
{ {
const page = workspace.createDoc({ id: 'page0' }); const page = docCollection.createDoc({ id: 'page0' });
page.load(); page.load();
const pageBlockId = page.addBlock( const pageBlockId = page.addBlock(
'affine:page' as keyof BlockSuite.BlockModels 'affine:page' as keyof BlockSuite.BlockModels
@@ -190,7 +190,7 @@ describe('indexeddb provider', () => {
); );
} }
{ {
const updates = await getUpdates(workspace.id); const updates = await getUpdates(docCollection.id);
expect(updates.length).toBe(1); expect(updates.length).toBe(1);
expect(updates[0]).toEqual(snapshot); expect(updates[0]).toEqual(snapshot);
} }
@@ -199,7 +199,7 @@ describe('indexeddb provider', () => {
expect(provider.connected).toBe(true); expect(provider.connected).toBe(true);
await setTimeout(200); await setTimeout(200);
{ {
const updates = await getUpdates(workspace.id); const updates = await getUpdates(docCollection.id);
expect(updates).not.toEqual([]); expect(updates).not.toEqual([]);
} }
expect(provider.connected).toBe(true); expect(provider.connected).toBe(true);
@@ -208,7 +208,7 @@ describe('indexeddb provider', () => {
}); });
test('cleanup', async () => { test('cleanup', async () => {
const provider = createIndexedDBProvider(workspace.doc); const provider = createIndexedDBProvider(docCollection.doc);
provider.connect(); provider.connect();
await setTimeout(200); await setTimeout(200);
const db = await openDB(rootDBName, dbVersion); const db = await openDB(rootDBName, dbVersion);
@@ -218,7 +218,7 @@ describe('indexeddb provider', () => {
.transaction('workspace', 'readonly') .transaction('workspace', 'readonly')
.objectStore('workspace'); .objectStore('workspace');
const keys = await store.getAllKeys(); const keys = await store.getAllKeys();
expect(keys).contain(workspace.id); expect(keys).contain(docCollection.id);
} }
await provider.cleanup(); await provider.cleanup();
@@ -229,16 +229,16 @@ describe('indexeddb provider', () => {
.transaction('workspace', 'readonly') .transaction('workspace', 'readonly')
.objectStore('workspace'); .objectStore('workspace');
const keys = await store.getAllKeys(); const keys = await store.getAllKeys();
expect(keys).not.contain(workspace.id); expect(keys).not.contain(docCollection.id);
} }
}); });
test('merge', async () => { test('merge', async () => {
setMergeCount(5); setMergeCount(5);
const provider = createIndexedDBProvider(workspace.doc, rootDBName); const provider = createIndexedDBProvider(docCollection.doc, rootDBName);
provider.connect(); provider.connect();
{ {
const page = workspace.createDoc({ id: 'page0' }); const page = docCollection.createDoc({ id: 'page0' });
page.load(); page.load();
const pageBlockId = page.addBlock( const pageBlockId = page.addBlock(
'affine:page' as keyof BlockSuite.BlockModels 'affine:page' as keyof BlockSuite.BlockModels
@@ -264,7 +264,7 @@ describe('indexeddb provider', () => {
}); });
test("data won't be lost", async () => { test("data won't be lost", async () => {
const doc = new Workspace.Y.Doc(); const doc = new DocCollection.Y.Doc();
const map = doc.getMap('map'); const map = doc.getMap('map');
for (let i = 0; i < 100; i++) { for (let i = 0; i < 100; i++) {
map.set(`${i}`, i); map.set(`${i}`, i);
@@ -275,7 +275,7 @@ describe('indexeddb provider', () => {
provider.disconnect(); provider.disconnect();
} }
{ {
const newDoc = new Workspace.Y.Doc(); const newDoc = new DocCollection.Y.Doc();
const provider = createIndexedDBProvider(newDoc, rootDBName); const provider = createIndexedDBProvider(newDoc, rootDBName);
provider.connect(); provider.connect();
provider.disconnect(); provider.disconnect();
@@ -412,14 +412,14 @@ describe('subDoc', () => {
}); });
test('blocksuite', async () => { test('blocksuite', async () => {
const page0 = workspace.createDoc({ const page0 = docCollection.createDoc({
id: 'page0', id: 'page0',
}); });
page0.load(); page0.load();
const { paragraphBlockId: paragraphBlockIdPage1 } = initEmptyPage(page0); const { paragraphBlockId: paragraphBlockIdPage1 } = initEmptyPage(page0);
const provider = createIndexedDBProvider(workspace.doc, rootDBName); const provider = createIndexedDBProvider(docCollection.doc, rootDBName);
provider.connect(); provider.connect();
const page1 = workspace.createDoc({ const page1 = docCollection.createDoc({
id: 'page1', id: 'page1',
}); });
page1.load(); page1.load();
@@ -427,22 +427,22 @@ describe('subDoc', () => {
await setTimeout(200); await setTimeout(200);
provider.disconnect(); provider.disconnect();
{ {
const newWorkspace = new Workspace({ const docCollection = new DocCollection({
id, id,
schema, schema,
}); });
const provider = createIndexedDBProvider(newWorkspace.doc, rootDBName); const provider = createIndexedDBProvider(docCollection.doc, rootDBName);
provider.connect(); provider.connect();
await setTimeout(200); await setTimeout(200);
const page0 = newWorkspace.getDoc('page0') as Doc; const page0 = docCollection.getDoc('page0') as Doc;
page0.load(); page0.load();
await setTimeout(200); await setTimeout(200);
{ {
const block = page0.getBlockById(paragraphBlockIdPage1); const block = page0.getBlockById(paragraphBlockIdPage1);
assertExists(block); assertExists(block);
} }
const page1 = newWorkspace.getDoc('page1') as Doc; const page1 = docCollection.getDoc('page1') as Doc;
page1.load(); page1.load();
await setTimeout(200); await setTimeout(200);
{ {
@@ -455,30 +455,30 @@ describe('subDoc', () => {
describe('utils', () => { describe('utils', () => {
test('download binary', async () => { test('download binary', async () => {
const page = workspace.createDoc({ id: 'page0' }); const page = docCollection.createDoc({ id: 'page0' });
page.load(); page.load();
initEmptyPage(page); initEmptyPage(page);
const provider = createIndexedDBProvider(workspace.doc, rootDBName); const provider = createIndexedDBProvider(docCollection.doc, rootDBName);
provider.connect(); provider.connect();
await setTimeout(200); await setTimeout(200);
provider.disconnect(); provider.disconnect();
const update = (await downloadBinary( const update = (await downloadBinary(
workspace.id, docCollection.id,
rootDBName rootDBName
)) as Uint8Array; )) as Uint8Array;
expect(update).toBeInstanceOf(Uint8Array); expect(update).toBeInstanceOf(Uint8Array);
const newWorkspace = new Workspace({ const newDocCollection = new DocCollection({
id, id,
schema, schema,
}); });
applyUpdate(newWorkspace.doc, update); applyUpdate(newDocCollection.doc, update);
await setTimeout(); await setTimeout();
expect(workspace.doc.toJSON()['meta']).toEqual( expect(docCollection.doc.toJSON()['meta']).toEqual(
newWorkspace.doc.toJSON()['meta'] newDocCollection.doc.toJSON()['meta']
); );
expect(Object.keys(workspace.doc.toJSON()['spaces'])).toEqual( expect(Object.keys(docCollection.doc.toJSON()['spaces'])).toEqual(
Object.keys(newWorkspace.doc.toJSON()['spaces']) Object.keys(newDocCollection.doc.toJSON()['spaces'])
); );
}); });

View File

@@ -24,7 +24,7 @@
"build": "vite build" "build": "vite build"
}, },
"devDependencies": { "devDependencies": {
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"vite": "^5.1.4", "vite": "^5.1.4",
"vite-plugin-dts": "3.7.3", "vite-plugin-dts": "3.7.3",
"vitest": "1.3.1", "vitest": "1.3.1",

View File

@@ -72,12 +72,12 @@
"uuid": "^9.0.1" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@blocksuite/blocks": "0.13.0-canary-202403050653-934469c", "@blocksuite/blocks": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/global": "0.13.0-canary-202403050653-934469c", "@blocksuite/global": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/icons": "2.1.45", "@blocksuite/icons": "2.1.45",
"@blocksuite/lit": "0.13.0-canary-202403050653-934469c", "@blocksuite/lit": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/presets": "0.13.0-canary-202403050653-934469c", "@blocksuite/presets": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"@storybook/addon-actions": "^7.6.17", "@storybook/addon-actions": "^7.6.17",
"@storybook/addon-essentials": "^7.6.17", "@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17", "@storybook/addon-interactions": "^7.6.17",

View File

@@ -25,14 +25,14 @@
"@affine/i18n": "workspace:*", "@affine/i18n": "workspace:*",
"@affine/templates": "workspace:*", "@affine/templates": "workspace:*",
"@affine/workspace-impl": "workspace:*", "@affine/workspace-impl": "workspace:*",
"@blocksuite/block-std": "0.13.0-canary-202403050653-934469c", "@blocksuite/block-std": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/blocks": "0.13.0-canary-202403050653-934469c", "@blocksuite/blocks": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/global": "0.13.0-canary-202403050653-934469c", "@blocksuite/global": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/icons": "2.1.45", "@blocksuite/icons": "2.1.45",
"@blocksuite/inline": "0.13.0-canary-202403050653-934469c", "@blocksuite/inline": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/lit": "0.13.0-canary-202403050653-934469c", "@blocksuite/lit": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/presets": "0.13.0-canary-202403050653-934469c", "@blocksuite/presets": "0.13.0-canary-202403120738-e15d583",
"@blocksuite/store": "0.13.0-canary-202403050653-934469c", "@blocksuite/store": "0.13.0-canary-202403120738-e15d583",
"@dnd-kit/core": "^6.1.0", "@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0", "@dnd-kit/sortable": "^8.0.0",

View File

@@ -1,7 +1,7 @@
import { WorkspaceSubPath } from '@affine/core/shared'; import { WorkspaceSubPath } from '@affine/core/shared';
import type { useAFFiNEI18N } from '@affine/i18n/hooks'; import type { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ArrowRightBigIcon } from '@blocksuite/icons'; import { ArrowRightBigIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { registerAffineCommand } from '@toeverything/infra/command'; import { registerAffineCommand } from '@toeverything/infra/command';
import type { createStore } from 'jotai'; import type { createStore } from 'jotai';
@@ -11,13 +11,13 @@ import type { useNavigateHelper } from '../hooks/use-navigate-helper';
export function registerAffineNavigationCommands({ export function registerAffineNavigationCommands({
t, t,
store, store,
workspace, docCollection,
navigationHelper, navigationHelper,
}: { }: {
t: ReturnType<typeof useAFFiNEI18N>; t: ReturnType<typeof useAFFiNEI18N>;
store: ReturnType<typeof createStore>; store: ReturnType<typeof createStore>;
navigationHelper: ReturnType<typeof useNavigateHelper>; navigationHelper: ReturnType<typeof useNavigateHelper>;
workspace: Workspace; docCollection: DocCollection;
}) { }) {
const unsubs: Array<() => void> = []; const unsubs: Array<() => void> = [];
unsubs.push( unsubs.push(
@@ -27,7 +27,7 @@ export function registerAffineNavigationCommands({
icon: <ArrowRightBigIcon />, icon: <ArrowRightBigIcon />,
label: t['com.affine.cmdk.affine.navigation.goto-all-pages'](), label: t['com.affine.cmdk.affine.navigation.goto-all-pages'](),
run() { run() {
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.ALL); navigationHelper.jumpToSubPath(docCollection.id, WorkspaceSubPath.ALL);
}, },
}) })
); );
@@ -39,7 +39,7 @@ export function registerAffineNavigationCommands({
icon: <ArrowRightBigIcon />, icon: <ArrowRightBigIcon />,
label: 'Go to Collection List', label: 'Go to Collection List',
run() { run() {
navigationHelper.jumpToCollections(workspace.id); navigationHelper.jumpToCollections(docCollection.id);
}, },
}) })
); );
@@ -51,7 +51,7 @@ export function registerAffineNavigationCommands({
icon: <ArrowRightBigIcon />, icon: <ArrowRightBigIcon />,
label: 'Go to Tag List', label: 'Go to Tag List',
run() { run() {
navigationHelper.jumpToTags(workspace.id); navigationHelper.jumpToTags(docCollection.id);
}, },
}) })
); );
@@ -91,7 +91,10 @@ export function registerAffineNavigationCommands({
icon: <ArrowRightBigIcon />, icon: <ArrowRightBigIcon />,
label: t['com.affine.cmdk.affine.navigation.goto-trash'](), label: t['com.affine.cmdk.affine.navigation.goto-trash'](),
run() { run() {
navigationHelper.jumpToSubPath(workspace.id, WorkspaceSubPath.TRASH); navigationHelper.jumpToSubPath(
docCollection.id,
WorkspaceSubPath.TRASH
);
}, },
}) })
); );

View File

@@ -14,7 +14,7 @@ const SyncAwarenessInnerLoggedIn = () => {
useEffect(() => { useEffect(() => {
if (user && currentWorkspace) { if (user && currentWorkspace) {
currentWorkspace.blockSuiteWorkspace.awarenessStore.awareness.setLocalStateField( currentWorkspace.docCollection.awarenessStore.awareness.setLocalStateField(
'user', 'user',
{ {
name: user.name, name: user.name,
@@ -23,7 +23,7 @@ const SyncAwarenessInnerLoggedIn = () => {
); );
return () => { return () => {
currentWorkspace.blockSuiteWorkspace.awarenessStore.awareness.setLocalStateField( currentWorkspace.docCollection.awarenessStore.awareness.setLocalStateField(
'user', 'user',
null null
); );

View File

@@ -1,5 +1,5 @@
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useBlockSuiteWorkspacePage } from '@affine/core/hooks/use-block-suite-workspace-page'; import { useDocCollectionPage } from '@affine/core/hooks/use-block-suite-workspace-page';
import { timestampToLocalDate } from '@affine/core/utils'; import { timestampToLocalDate } from '@affine/core/utils';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import { import {
@@ -10,7 +10,7 @@ import {
} from '@affine/graphql'; } from '@affine/graphql';
import { AffineCloudBlobStorage } from '@affine/workspace-impl'; import { AffineCloudBlobStorage } from '@affine/workspace-impl';
import { assertEquals } from '@blocksuite/global/utils'; import { assertEquals } from '@blocksuite/global/utils';
import { Workspace } from '@blocksuite/store'; import { DocCollection } from '@blocksuite/store';
import { globalBlockSuiteSchema } from '@toeverything/infra'; import { globalBlockSuiteSchema } from '@toeverything/infra';
import { revertUpdate } from '@toeverything/y-indexeddb'; import { revertUpdate } from '@toeverything/y-indexeddb';
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
@@ -98,14 +98,14 @@ const snapshotFetcher = async (
// so that we do not need to worry about providers etc // so that we do not need to worry about providers etc
// todo: fix references to the page (the referenced page will shown as deleted) // todo: fix references to the page (the referenced page will shown as deleted)
// if we simply clone the current workspace, it maybe time consuming right? // if we simply clone the current workspace, it maybe time consuming right?
const workspaceMap = new Map<string, Workspace>(); const docCollectionMap = new Map<string, DocCollection>();
// assume the workspace is a cloud workspace since the history feature is only enabled for cloud workspace // assume the workspace is a cloud workspace since the history feature is only enabled for cloud workspace
const getOrCreateShellWorkspace = (workspaceId: string) => { const getOrCreateShellWorkspace = (workspaceId: string) => {
let workspace = workspaceMap.get(workspaceId); let docCollection = docCollectionMap.get(workspaceId);
if (!workspace) { if (!docCollection) {
const blobStorage = new AffineCloudBlobStorage(workspaceId); const blobStorage = new AffineCloudBlobStorage(workspaceId);
workspace = new Workspace({ docCollection = new DocCollection({
id: workspaceId, id: workspaceId,
blobStorages: [ blobStorages: [
() => ({ () => ({
@@ -114,10 +114,10 @@ const getOrCreateShellWorkspace = (workspaceId: string) => {
], ],
schema: globalBlockSuiteSchema, schema: globalBlockSuiteSchema,
}); });
workspaceMap.set(workspaceId, workspace); docCollectionMap.set(workspaceId, docCollection);
workspace.doc.emit('sync', []); docCollection.doc.emit('sync', []);
} }
return workspace; return docCollection;
}; };
// workspace id + page id + timestamp -> snapshot (update binary) // workspace id + page id + timestamp -> snapshot (update binary)
@@ -139,17 +139,17 @@ export const usePageHistory = (
// workspace id + page id + timestamp + snapshot -> Page (to be used for rendering in blocksuite editor) // workspace id + page id + timestamp + snapshot -> Page (to be used for rendering in blocksuite editor)
export const useSnapshotPage = ( export const useSnapshotPage = (
workspace: Workspace, docCollection: DocCollection,
pageDocId: string, pageDocId: string,
ts?: string ts?: string
) => { ) => {
const snapshot = usePageHistory(workspace.id, pageDocId, ts); const snapshot = usePageHistory(docCollection.id, pageDocId, ts);
const page = useMemo(() => { const page = useMemo(() => {
if (!ts) { if (!ts) {
return; return;
} }
const pageId = pageDocId + '-' + ts; const pageId = pageDocId + '-' + ts;
const historyShellWorkspace = getOrCreateShellWorkspace(workspace.id); const historyShellWorkspace = getOrCreateShellWorkspace(docCollection.id);
let page = historyShellWorkspace.getDoc(pageId); let page = historyShellWorkspace.getDoc(pageId);
if (!page && snapshot) { if (!page && snapshot) {
page = historyShellWorkspace.createDoc({ page = historyShellWorkspace.createDoc({
@@ -163,15 +163,15 @@ export const useSnapshotPage = (
}); // must load before applyUpdate }); // must load before applyUpdate
} }
return page ?? undefined; return page ?? undefined;
}, [pageDocId, snapshot, ts, workspace]); }, [pageDocId, snapshot, ts, docCollection]);
useEffect(() => { useEffect(() => {
const historyShellWorkspace = getOrCreateShellWorkspace(workspace.id); const historyShellWorkspace = getOrCreateShellWorkspace(docCollection.id);
// apply the rootdoc's update to the current workspace // apply the rootdoc's update to the current workspace
// this makes sure the page reference links are not deleted ones in the preview // this makes sure the page reference links are not deleted ones in the preview
const update = encodeStateAsUpdate(workspace.doc); const update = encodeStateAsUpdate(docCollection.doc);
applyUpdate(historyShellWorkspace.doc, update); applyUpdate(historyShellWorkspace.doc, update);
}, [workspace]); }, [docCollection]);
return page; return page;
}; };
@@ -187,13 +187,16 @@ export const historyListGroupByDay = (histories: DocHistory[]) => {
return [...map.entries()]; return [...map.entries()];
}; };
export const useRestorePage = (workspace: Workspace, pageId: string) => { export const useRestorePage = (
const page = useBlockSuiteWorkspacePage(workspace, pageId); docCollection: DocCollection,
pageId: string
) => {
const page = useDocCollectionPage(docCollection, pageId);
const mutateQueryResource = useMutateQueryResource(); const mutateQueryResource = useMutateQueryResource();
const { trigger: recover, isMutating } = useMutation({ const { trigger: recover, isMutating } = useMutation({
mutation: recoverDocMutation, mutation: recoverDocMutation,
}); });
const { getDocMeta, setDocTitle } = useDocMetaHelper(workspace); const { getDocMeta, setDocTitle } = useDocMetaHelper(docCollection);
const onRestore = useMemo(() => { const onRestore = useMemo(() => {
return async (version: string, update: Uint8Array) => { return async (version: string, update: Uint8Array) => {
@@ -216,12 +219,12 @@ export const useRestorePage = (workspace: Workspace, pageId: string) => {
await recover({ await recover({
docId: pageDocId, docId: pageDocId,
timestamp: version, timestamp: version,
workspaceId: workspace.id, workspaceId: docCollection.id,
}); });
await mutateQueryResource(listHistoryQuery, vars => { await mutateQueryResource(listHistoryQuery, vars => {
return ( return (
vars.pageDocId === pageDocId && vars.workspaceId === workspace.id vars.pageDocId === pageDocId && vars.workspaceId === docCollection.id
); );
}); });
@@ -234,7 +237,7 @@ export const useRestorePage = (workspace: Workspace, pageId: string) => {
pageId, pageId,
recover, recover,
setDocTitle, setDocTitle,
workspace.id, docCollection.id,
]); ]);
return { return {

View File

@@ -5,13 +5,13 @@ import { ConfirmModal, Modal } from '@affine/component/ui/modal';
import { openSettingModalAtom } from '@affine/core/atoms'; import { openSettingModalAtom } from '@affine/core/atoms';
import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner'; import { useIsWorkspaceOwner } from '@affine/core/hooks/affine/use-is-workspace-owner';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useBlockSuiteWorkspacePageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title'; import { useDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
import { useWorkspaceQuota } from '@affine/core/hooks/use-workspace-quota'; import { useWorkspaceQuota } from '@affine/core/hooks/use-workspace-quota';
import { Trans } from '@affine/i18n'; import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons'; import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons';
import type { Doc as BlockSuiteDoc } from '@blocksuite/store'; import type { Doc as BlockSuiteDoc } from '@blocksuite/store';
import { type Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import { type DocCollection } from '@blocksuite/store';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import type { DialogContentProps } from '@radix-ui/react-dialog'; import type { DialogContentProps } from '@radix-ui/react-dialog';
import { Doc, type PageMode, Workspace } from '@toeverything/infra'; import { Doc, type PageMode, Workspace } from '@toeverything/infra';
@@ -49,7 +49,7 @@ import * as styles from './styles.css';
export interface PageHistoryModalProps { export interface PageHistoryModalProps {
open: boolean; open: boolean;
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
workspace: BlockSuiteWorkspace; docCollection: DocCollection;
pageId: string; pageId: string;
} }
@@ -444,26 +444,26 @@ const EmptyHistoryPrompt = () => {
}; };
const PageHistoryManager = ({ const PageHistoryManager = ({
workspace, docCollection,
pageId, pageId,
onClose, onClose,
}: { }: {
workspace: BlockSuiteWorkspace; docCollection: DocCollection;
pageId: string; pageId: string;
onClose: () => void; onClose: () => void;
}) => { }) => {
const workspaceId = workspace.id; const workspaceId = docCollection.id;
const [activeVersion, setActiveVersion] = useState<string>(); const [activeVersion, setActiveVersion] = useState<string>();
const pageDocId = useMemo(() => { const pageDocId = useMemo(() => {
return workspace.getDoc(pageId)?.spaceDoc.guid ?? pageId; return docCollection.getDoc(pageId)?.spaceDoc.guid ?? pageId;
}, [pageId, workspace]); }, [pageId, docCollection]);
const snapshotPage = useSnapshotPage(workspace, pageDocId, activeVersion); const snapshotPage = useSnapshotPage(docCollection, pageDocId, activeVersion);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const { onRestore, isMutating } = useRestorePage(workspace, pageId); const { onRestore, isMutating } = useRestorePage(docCollection, pageId);
const handleRestore = useMemo( const handleRestore = useMemo(
() => async () => { () => async () => {
@@ -481,7 +481,7 @@ const PageHistoryManager = ({
const page = useService(Doc); const page = useService(Doc);
const [mode, setMode] = useState<PageMode>(page.mode.value); const [mode, setMode] = useState<PageMode>(page.mode.value);
const title = useBlockSuiteWorkspacePageTitle(workspace, pageId); const title = useDocCollectionPageTitle(docCollection, pageId);
const [showRestoreConfirmModal, setShowRestoreConfirmModal] = useState(false); const [showRestoreConfirmModal, setShowRestoreConfirmModal] = useState(false);
@@ -558,7 +558,7 @@ export const PageHistoryModal = ({
onOpenChange, onOpenChange,
open, open,
pageId, pageId,
workspace, docCollection: workspace,
}: PageHistoryModalProps) => { }: PageHistoryModalProps) => {
const onClose = useCallback(() => { const onClose = useCallback(() => {
onOpenChange(false); onOpenChange(false);
@@ -570,7 +570,7 @@ export const PageHistoryModal = ({
<PageHistoryManager <PageHistoryManager
onClose={onClose} onClose={onClose}
pageId={pageId} pageId={pageId}
workspace={workspace} docCollection={workspace}
/> />
</Suspense> </Suspense>
</ModalContainer> </ModalContainer>
@@ -595,7 +595,7 @@ export const GlobalPageHistoryModal = () => {
open={open} open={open}
onOpenChange={handleOpenChange} onOpenChange={handleOpenChange}
pageId={pageId} pageId={pageId}
workspace={workspace.blockSuiteWorkspace} docCollection={workspace.docCollection}
/> />
); );
}; };

View File

@@ -124,7 +124,7 @@ export class PagePropertiesMetaManager {
// returns page schema properties -> related page // returns page schema properties -> related page
getPropertyStatistics() { getPropertyStatistics() {
const mapping = new Map<string, Set<string>>(); const mapping = new Map<string, Set<string>>();
for (const page of this.adapter.workspace.blockSuiteWorkspace.docs.values()) { for (const page of this.adapter.workspace.docCollection.docs.values()) {
const properties = this.adapter.getPageProperties(page.id); const properties = this.adapter.getPageProperties(page.id);
for (const id of Object.keys(properties.custom)) { for (const id of Object.keys(properties.custom)) {
if (!mapping.has(id)) mapping.set(id, new Set()); if (!mapping.has(id)) mapping.set(id, new Set());
@@ -169,7 +169,7 @@ export class PagePropertiesManager {
} }
get page() { get page() {
return this.adapter.workspace.blockSuiteWorkspace.getDoc(this.pageId); return this.adapter.workspace.docCollection.getDoc(this.pageId);
} }
get intrinsicMeta() { get intrinsicMeta() {

View File

@@ -177,8 +177,8 @@ export const NumberValue = ({ property }: PropertyRowValueProps) => {
export const TagsValue = () => { export const TagsValue = () => {
const workspace = useService(Workspace); const workspace = useService(Workspace);
const page = useService(Doc); const page = useService(Doc);
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const pageMetas = useAllBlockSuiteDocMeta(blockSuiteWorkspace); const pageMetas = useAllBlockSuiteDocMeta(docCollection);
const legacyProperties = useService(WorkspaceLegacyProperties); const legacyProperties = useService(WorkspaceLegacyProperties);
const options = useLiveData(legacyProperties.tagOptions$); const options = useLiveData(legacyProperties.tagOptions$);

View File

@@ -405,7 +405,7 @@ export const PageBacklinksPopup = ({
key={pageId} key={pageId}
wrapper={MenuItem} wrapper={MenuItem}
pageId={pageId} pageId={pageId}
workspace={manager.workspace.blockSuiteWorkspace} docCollection={manager.workspace.docCollection}
/> />
))} ))}
</div> </div>
@@ -600,7 +600,7 @@ export const PagePropertiesTableHeader = ({
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const backlinks = useBlockSuitePageBacklinks( const backlinks = useBlockSuitePageBacklinks(
manager.workspace.blockSuiteWorkspace, manager.workspace.docCollection,
manager.pageId manager.pageId
); );
@@ -1015,7 +1015,7 @@ export const PagePropertiesAddProperty = () => {
const PagePropertiesTableInner = () => { const PagePropertiesTableInner = () => {
const manager = useContext(managerContext); const manager = useContext(managerContext);
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
use(manager.workspace.blockSuiteWorkspace.doc.whenSynced); use(manager.workspace.docCollection.doc.whenSynced);
return ( return (
<div className={styles.root}> <div className={styles.root}>
<Collapsible.Root <Collapsible.Root

View File

@@ -3,7 +3,7 @@ import { useJournalHelper } from '@affine/core/hooks/use-journal';
import { WorkbenchLink } from '@affine/core/modules/workbench'; import { WorkbenchLink } from '@affine/core/modules/workbench';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { LinkedPageIcon, TodayIcon } from '@blocksuite/icons'; import { LinkedPageIcon, TodayIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { PropsWithChildren } from 'react'; import type { PropsWithChildren } from 'react';
import * as styles from './styles.css'; import * as styles from './styles.css';
@@ -44,15 +44,15 @@ export function pageReferenceRenderer({
export function AffinePageReference({ export function AffinePageReference({
pageId, pageId,
workspace, docCollection,
wrapper: Wrapper, wrapper: Wrapper,
}: { }: {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
wrapper?: React.ComponentType<PropsWithChildren>; wrapper?: React.ComponentType<PropsWithChildren>;
}) { }) {
const pageMetaHelper = useDocMetaHelper(workspace); const pageMetaHelper = useDocMetaHelper(docCollection);
const journalHelper = useJournalHelper(workspace); const journalHelper = useJournalHelper(docCollection);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const el = pageReferenceRenderer({ const el = pageReferenceRenderer({
pageId, pageId,

View File

@@ -46,17 +46,13 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
const avatarUrl = useWorkspaceBlobObjectUrl(workspace?.meta, avatarBlob); const avatarUrl = useWorkspaceBlobObjectUrl(workspace?.meta, avatarBlob);
useEffect(() => { useEffect(() => {
if (workspace?.blockSuiteWorkspace) { if (workspace?.docCollection) {
setAvatarBlob(workspace.blockSuiteWorkspace.meta.avatar ?? null); setAvatarBlob(workspace.docCollection.meta.avatar ?? null);
setName( setName(workspace.docCollection.meta.name ?? UNTITLED_WORKSPACE_NAME);
workspace.blockSuiteWorkspace.meta.name ?? UNTITLED_WORKSPACE_NAME const dispose = workspace.docCollection.meta.commonFieldsUpdated.on(
);
const dispose = workspace.blockSuiteWorkspace.meta.commonFieldsUpdated.on(
() => { () => {
setAvatarBlob(workspace.blockSuiteWorkspace.meta.avatar ?? null); setAvatarBlob(workspace.docCollection.meta.avatar ?? null);
setName( setName(workspace.docCollection.meta.name ?? UNTITLED_WORKSPACE_NAME);
workspace.blockSuiteWorkspace.meta.name ?? UNTITLED_WORKSPACE_NAME
);
} }
); );
return () => { return () => {
@@ -75,14 +71,14 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
return; return;
} }
if (!file) { if (!file) {
workspace.blockSuiteWorkspace.meta.setAvatar(''); workspace.docCollection.meta.setAvatar('');
return; return;
} }
try { try {
const reducedFile = await validateAndReduceImage(file); const reducedFile = await validateAndReduceImage(file);
const blobs = workspace.blockSuiteWorkspace.blob; const blobs = workspace.docCollection.blob;
const blobId = await blobs.set(reducedFile); const blobId = await blobs.set(reducedFile);
workspace.blockSuiteWorkspace.meta.setAvatar(blobId); workspace.docCollection.meta.setAvatar(blobId);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
throw error; throw error;
@@ -96,7 +92,7 @@ export const ProfilePanel = ({ isOwner, workspace }: ProfilePanelProps) => {
if (!workspace) { if (!workspace) {
return; return;
} }
workspace.blockSuiteWorkspace.meta.setName(name); workspace.docCollection.meta.setName(name);
}, },
[workspace] [workspace]
); );

View File

@@ -110,8 +110,8 @@ const BlockSuiteEditorImpl = forwardRef<AffineEditorContainer, EditorProps>(
}; };
}, []); }, []);
const pageMetaHelper = useDocMetaHelper(page.workspace); const pageMetaHelper = useDocMetaHelper(page.collection);
const journalHelper = useJournalHelper(page.workspace); const journalHelper = useJournalHelper(page.collection);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const customRenderers = useMemo(() => { const customRenderers = useMemo(() => {

View File

@@ -6,7 +6,7 @@ import * as styles from './styles.css';
export const BlocksuiteEditorJournalDocTitle = ({ page }: { page: Doc }) => { export const BlocksuiteEditorJournalDocTitle = ({ page }: { page: Doc }) => {
const { localizedJournalDate, isTodayJournal, journalDate } = const { localizedJournalDate, isTodayJournal, journalDate } =
useJournalInfoHelper(page.workspace, page.id); useJournalInfoHelper(page.collection, page.id);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
// TODO: i18n // TODO: i18n

View File

@@ -64,7 +64,7 @@ export const BlocksuiteDocEditor = forwardRef<
const docRef = useRef<PageEditor | null>(null); const docRef = useRef<PageEditor | null>(null);
const [docPage, setDocPage] = const [docPage, setDocPage] =
useState<HTMLElementTagNameMap['affine-page-root']>(); useState<HTMLElementTagNameMap['affine-page-root']>();
const { isJournal } = useJournalInfoHelper(page.workspace, page.id); const { isJournal } = useJournalInfoHelper(page.collection, page.id);
const onDocRef = useCallback( const onDocRef = useCallback(
(el: PageEditor) => { (el: PageEditor) => {

View File

@@ -15,17 +15,17 @@ export interface FavoriteButtonProps {
export const useFavorite = (pageId: string) => { export const useFavorite = (pageId: string) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const currentPage = blockSuiteWorkspace.getDoc(pageId); const currentPage = docCollection.getDoc(pageId);
assertExists(currentPage); assertExists(currentPage);
const pageMeta = useBlockSuiteDocMeta(blockSuiteWorkspace).find( const pageMeta = useBlockSuiteDocMeta(docCollection).find(
meta => meta.id === pageId meta => meta.id === pageId
); );
const favorite = pageMeta?.favorite ?? false; const favorite = pageMeta?.favorite ?? false;
const { toggleFavorite: _toggleFavorite } = const { toggleFavorite: _toggleFavorite } =
useBlockSuiteMetaHelper(blockSuiteWorkspace); useBlockSuiteMetaHelper(docCollection);
const toggleFavorite = useCallback(() => { const toggleFavorite = useCallback(() => {
_toggleFavorite(pageId); _toggleFavorite(pageId);

View File

@@ -3,24 +3,24 @@ import {
useJournalInfoHelper, useJournalInfoHelper,
useJournalRouteHelper, useJournalRouteHelper,
} from '@affine/core/hooks/use-journal'; } from '@affine/core/hooks/use-journal';
import type { BlockSuiteWorkspace } from '@affine/core/shared'; import type { DocCollection } from '@affine/core/shared';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
export interface JournalWeekDatePickerProps { export interface JournalWeekDatePickerProps {
workspace: BlockSuiteWorkspace; docCollection: DocCollection;
page: Doc; page: Doc;
} }
const weekStyle = { maxWidth: 800, width: '100%' }; const weekStyle = { maxWidth: 800, width: '100%' };
export const JournalWeekDatePicker = ({ export const JournalWeekDatePicker = ({
workspace, docCollection,
page, page,
}: JournalWeekDatePickerProps) => { }: JournalWeekDatePickerProps) => {
const handleRef = useRef<WeekDatePickerHandle>(null); const handleRef = useRef<WeekDatePickerHandle>(null);
const { journalDate } = useJournalInfoHelper(workspace, page.id); const { journalDate } = useJournalInfoHelper(docCollection, page.id);
const { openJournal } = useJournalRouteHelper(workspace); const { openJournal } = useJournalRouteHelper(docCollection);
const [date, setDate] = useState( const [date, setDate] = useState(
(journalDate ?? dayjs()).format('YYYY-MM-DD') (journalDate ?? dayjs()).format('YYYY-MM-DD')
); );

View File

@@ -1,16 +1,18 @@
import { Button } from '@affine/component'; import { Button } from '@affine/component';
import { useJournalRouteHelper } from '@affine/core/hooks/use-journal'; import { useJournalRouteHelper } from '@affine/core/hooks/use-journal';
import type { BlockSuiteWorkspace } from '@affine/core/shared'; import type { DocCollection } from '@affine/core/shared';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useCallback } from 'react'; import { useCallback } from 'react';
export interface JournalTodayButtonProps { export interface JournalTodayButtonProps {
workspace: BlockSuiteWorkspace; docCollection: DocCollection;
} }
export const JournalTodayButton = ({ workspace }: JournalTodayButtonProps) => { export const JournalTodayButton = ({
docCollection,
}: JournalTodayButtonProps) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const journalHelper = useJournalRouteHelper(workspace); const journalHelper = useJournalRouteHelper(docCollection);
const onToday = useCallback(() => { const onToday = useCallback(() => {
journalHelper.openToday(); journalHelper.openToday();

View File

@@ -47,11 +47,11 @@ export const PageHeaderMenuButton = ({
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const currentPage = blockSuiteWorkspace.getDoc(pageId); const currentPage = docCollection.getDoc(pageId);
assertExists(currentPage); assertExists(currentPage);
const pageMeta = useBlockSuiteDocMeta(blockSuiteWorkspace).find( const pageMeta = useBlockSuiteDocMeta(docCollection).find(
meta => meta.id === pageId meta => meta.id === pageId
); );
const page = useService(Doc); const page = useService(Doc);
@@ -59,9 +59,9 @@ export const PageHeaderMenuButton = ({
const { favorite, toggleFavorite } = useFavorite(pageId); const { favorite, toggleFavorite } = useFavorite(pageId);
const { duplicate } = useBlockSuiteMetaHelper(blockSuiteWorkspace); const { duplicate } = useBlockSuiteMetaHelper(docCollection);
const { importFile } = usePageHelper(blockSuiteWorkspace); const { importFile } = usePageHelper(docCollection);
const { setTrashModal } = useTrashModalHelper(blockSuiteWorkspace); const { setTrashModal } = useTrashModalHelper(docCollection);
const [historyModalOpen, setHistoryModalOpen] = useState(false); const [historyModalOpen, setHistoryModalOpen] = useState(false);
const setOpenHistoryTipsModal = useSetAtom(openHistoryTipsModalAtom); const setOpenHistoryTipsModal = useSetAtom(openHistoryTipsModalAtom);
@@ -227,7 +227,7 @@ export const PageHeaderMenuButton = ({
</Menu> </Menu>
{workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? ( {workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? (
<PageHistoryModal <PageHistoryModal
workspace={workspace.blockSuiteWorkspace} docCollection={workspace.docCollection}
open={historyModalOpen} open={historyModalOpen}
pageId={pageId} pageId={pageId}
onOpenChange={setHistoryModalOpen} onOpenChange={setHistoryModalOpen}

View File

@@ -3,14 +3,14 @@ import {
useBlockSuiteDocMeta, useBlockSuiteDocMeta,
useDocMetaHelper, useDocMetaHelper,
} from '@affine/core/hooks/use-block-suite-page-meta'; } from '@affine/core/hooks/use-block-suite-page-meta';
import type { BlockSuiteWorkspace } from '@affine/core/shared'; import type { DocCollection } from '@affine/core/shared';
import type { HTMLAttributes } from 'react'; import type { HTMLAttributes } from 'react';
import { useCallback } from 'react'; import { useCallback } from 'react';
import * as styles from './style.css'; import * as styles from './style.css';
export interface BlockSuiteHeaderTitleProps { export interface BlockSuiteHeaderTitleProps {
blockSuiteWorkspace: BlockSuiteWorkspace; docCollection: DocCollection;
pageId: string; pageId: string;
/** if set, title cannot be edited */ /** if set, title cannot be edited */
isPublic?: boolean; isPublic?: boolean;
@@ -21,18 +21,13 @@ const inputAttrs = {
'data-testid': 'title-content', 'data-testid': 'title-content',
} as HTMLAttributes<HTMLInputElement>; } as HTMLAttributes<HTMLInputElement>;
export const BlocksuiteHeaderTitle = (props: BlockSuiteHeaderTitleProps) => { export const BlocksuiteHeaderTitle = (props: BlockSuiteHeaderTitleProps) => {
const { const { docCollection, pageId, isPublic, inputHandleRef } = props;
blockSuiteWorkspace: workspace, const currentPage = docCollection.getDoc(pageId);
pageId, const pageMeta = useBlockSuiteDocMeta(docCollection).find(
isPublic,
inputHandleRef,
} = props;
const currentPage = workspace.getDoc(pageId);
const pageMeta = useBlockSuiteDocMeta(workspace).find(
meta => meta.id === currentPage?.id meta => meta.id === currentPage?.id
); );
const title = pageMeta?.title; const title = pageMeta?.title;
const { setDocTitle } = useDocMetaHelper(workspace); const { setDocTitle } = useDocMetaHelper(docCollection);
const onChange = useCallback( const onChange = useCallback(
(v: string) => { (v: string) => {

View File

@@ -10,14 +10,14 @@ import {
import type { CSSProperties } from 'react'; import type { CSSProperties } from 'react';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import type { BlockSuiteWorkspace } from '../../../shared'; import type { DocCollection } from '../../../shared';
import { toast } from '../../../utils'; import { toast } from '../../../utils';
import { StyledEditorModeSwitch, StyledKeyboardItem } from './style'; import { StyledEditorModeSwitch, StyledKeyboardItem } from './style';
import { EdgelessSwitchItem, PageSwitchItem } from './switch-items'; import { EdgelessSwitchItem, PageSwitchItem } from './switch-items';
export type EditorModeSwitchProps = { export type EditorModeSwitchProps = {
// todo(himself65): combine these two properties // todo(himself65): combine these two properties
blockSuiteWorkspace: BlockSuiteWorkspace; docCollection: DocCollection;
pageId: string; pageId: string;
style?: CSSProperties; style?: CSSProperties;
isPublic?: boolean; isPublic?: boolean;
@@ -36,13 +36,13 @@ const TooltipContent = () => {
}; };
export const EditorModeSwitch = ({ export const EditorModeSwitch = ({
style, style,
blockSuiteWorkspace, docCollection,
pageId, pageId,
isPublic, isPublic,
publicMode, publicMode,
}: EditorModeSwitchProps) => { }: EditorModeSwitchProps) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const pageMeta = useBlockSuiteDocMeta(blockSuiteWorkspace).find( const pageMeta = useBlockSuiteDocMeta(docCollection).find(
meta => meta.id === pageId meta => meta.id === pageId
); );
const trash = pageMeta?.trash ?? false; const trash = pageMeta?.trash ?? false;

View File

@@ -1,7 +1,7 @@
import { toast } from '@affine/component'; import { toast } from '@affine/component';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useBlockSuiteWorkspaceHelper } from '@affine/core/hooks/use-block-suite-workspace-helper'; import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
import { WorkspaceSubPath } from '@affine/core/shared'; import { WorkspaceSubPath } from '@affine/core/shared';
import { useService } from '@toeverything/infra'; import { useService } from '@toeverything/infra';
import { PageRecordList } from '@toeverything/infra'; import { PageRecordList } from '@toeverything/infra';
@@ -9,12 +9,12 @@ import { initEmptyPage } from '@toeverything/infra';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useNavigateHelper } from '../../../hooks/use-navigate-helper'; import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
import type { BlockSuiteWorkspace } from '../../../shared'; import type { DocCollection } from '../../../shared';
export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => { export const usePageHelper = (docCollection: DocCollection) => {
const { openPage, jumpToSubPath } = useNavigateHelper(); const { openPage, jumpToSubPath } = useNavigateHelper();
const { createDoc } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace); const { createDoc } = useDocCollectionHelper(docCollection);
const { setDocMeta } = useDocMetaHelper(blockSuiteWorkspace); const { setDocMeta } = useDocMetaHelper(docCollection);
const pageRecordList = useService(PageRecordList); const pageRecordList = useService(PageRecordList);
const isPreferredEdgeless = useCallback( const isPreferredEdgeless = useCallback(
@@ -28,10 +28,10 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
const page = createDoc(); const page = createDoc();
initEmptyPage(page); initEmptyPage(page);
pageRecordList.record(page.id).value?.setMode(mode || 'page'); pageRecordList.record(page.id).value?.setMode(mode || 'page');
openPage(blockSuiteWorkspace.id, page.id); openPage(docCollection.id, page.id);
return page; return page;
}, },
[blockSuiteWorkspace.id, createDoc, openPage, pageRecordList] [docCollection.id, createDoc, openPage, pageRecordList]
); );
const createEdgelessAndOpen = useCallback(() => { const createEdgelessAndOpen = useCallback(() => {
@@ -50,7 +50,7 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
}.` }.`
); );
if (options.isWorkspaceFile) { if (options.isWorkspaceFile) {
jumpToSubPath(blockSuiteWorkspace.id, WorkspaceSubPath.ALL); jumpToSubPath(docCollection.id, WorkspaceSubPath.ALL);
return; return;
} }
@@ -58,16 +58,16 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
return; return;
} }
const pageId = pageIds[0]; const pageId = pageIds[0];
openPage(blockSuiteWorkspace.id, pageId); openPage(docCollection.id, pageId);
}; };
showImportModal({ workspace: blockSuiteWorkspace, onSuccess }); showImportModal({ collection: docCollection, onSuccess });
}, [blockSuiteWorkspace, openPage, jumpToSubPath]); }, [docCollection, openPage, jumpToSubPath]);
const createLinkedPageAndOpen = useAsyncCallback( const createLinkedPageAndOpen = useAsyncCallback(
async (pageId: string) => { async (pageId: string) => {
const page = createPageAndOpen(); const page = createPageAndOpen();
page.load(); page.load();
const parentPage = blockSuiteWorkspace.getDoc(pageId); const parentPage = docCollection.getDoc(pageId);
if (parentPage) { if (parentPage) {
parentPage.load(); parentPage.load();
const text = parentPage.Text.fromDelta([ const text = parentPage.Text.fromDelta([
@@ -86,7 +86,7 @@ export const usePageHelper = (blockSuiteWorkspace: BlockSuiteWorkspace) => {
setDocMeta(page.id, {}); setDocMeta(page.id, {});
} }
}, },
[blockSuiteWorkspace, createPageAndOpen, setDocMeta] [docCollection, createPageAndOpen, setDocMeta]
); );
return useMemo(() => { return useMemo(() => {

View File

@@ -13,7 +13,7 @@ import {
PlusIcon, PlusIcon,
ViewBarIcon, ViewBarIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import clsx from 'clsx'; import clsx from 'clsx';
import { useErrorBoundary } from 'foxact/use-error-boundary'; import { useErrorBoundary } from 'foxact/use-error-boundary';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
@@ -45,7 +45,7 @@ import {
import { hasAnimationPlayedAtom, previewBlockIdAtom } from './index.jotai'; import { hasAnimationPlayedAtom, previewBlockIdAtom } from './index.jotai';
export type ImagePreviewModalProps = { export type ImagePreviewModalProps = {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
}; };
@@ -92,7 +92,7 @@ const ImagePreviewModalImpl = (
const nextImageHandler = useCallback( const nextImageHandler = useCallback(
(blockId: string | null) => { (blockId: string | null) => {
assertExists(blockId); assertExists(blockId);
const workspace = props.workspace; const workspace = props.docCollection;
if (!hasPlayedAnimation) { if (!hasPlayedAnimation) {
setHasPlayedAnimation(true); setHasPlayedAnimation(true);
} }
@@ -109,13 +109,13 @@ const ImagePreviewModalImpl = (
setBlockId(nextBlock.id); setBlockId(nextBlock.id);
} }
}, },
[props.pageId, props.workspace, setBlockId, hasPlayedAnimation] [props.pageId, props.docCollection, setBlockId, hasPlayedAnimation]
); );
const previousImageHandler = useCallback( const previousImageHandler = useCallback(
(blockId: string | null) => { (blockId: string | null) => {
assertExists(blockId); assertExists(blockId);
const workspace = props.workspace; const workspace = props.docCollection;
const page = workspace.getDoc(props.pageId); const page = workspace.getDoc(props.pageId);
assertExists(page); assertExists(page);
const block = page.getBlockById(blockId); const block = page.getBlockById(blockId);
@@ -130,12 +130,12 @@ const ImagePreviewModalImpl = (
} }
resetZoom(); resetZoom();
}, },
[props.pageId, props.workspace, setBlockId, resetZoom] [props.pageId, props.docCollection, setBlockId, resetZoom]
); );
const deleteHandler = useCallback( const deleteHandler = useCallback(
(blockId: string) => { (blockId: string) => {
const { pageId, workspace, onClose } = props; const { pageId, docCollection: workspace, onClose } = props;
const page = workspace.getDoc(pageId); const page = workspace.getDoc(pageId);
assertExists(page); assertExists(page);
@@ -185,7 +185,7 @@ const ImagePreviewModalImpl = (
const downloadHandler = useCallback( const downloadHandler = useCallback(
async (blockId: string | null) => { async (blockId: string | null) => {
const workspace = props.workspace; const workspace = props.docCollection;
const page = workspace.getDoc(props.pageId); const page = workspace.getDoc(props.pageId);
assertExists(page); assertExists(page);
if (typeof blockId === 'string') { if (typeof blockId === 'string') {
@@ -237,31 +237,31 @@ const ImagePreviewModalImpl = (
a.remove(); a.remove();
} }
}, },
[props.pageId, props.workspace] [props.pageId, props.docCollection]
); );
const [caption, setCaption] = useState(() => { const [caption, setCaption] = useState(() => {
const page = props.workspace.getDoc(props.pageId); const page = props.docCollection.getDoc(props.pageId);
assertExists(page); assertExists(page);
const block = page.getBlockById(props.blockId) as ImageBlockModel; const block = page.getBlockById(props.blockId) as ImageBlockModel;
assertExists(block); assertExists(block);
return block?.caption; return block?.caption;
}); });
useEffect(() => { useEffect(() => {
const page = props.workspace.getDoc(props.pageId); const page = props.docCollection.getDoc(props.pageId);
assertExists(page); assertExists(page);
const block = page.getBlockById(props.blockId) as ImageBlockModel; const block = page.getBlockById(props.blockId) as ImageBlockModel;
assertExists(block); assertExists(block);
setCaption(block?.caption); setCaption(block?.caption);
}, [props.blockId, props.pageId, props.workspace]); }, [props.blockId, props.pageId, props.docCollection]);
const { data, error } = useSWR( const { data, error } = useSWR(
['workspace', 'image', props.pageId, props.blockId], ['workspace', 'image', props.pageId, props.blockId],
{ {
fetcher: ([_, __, pageId, blockId]) => { fetcher: ([_, __, pageId, blockId]) => {
const page = props.workspace.getDoc(pageId); const page = props.docCollection.getDoc(pageId);
assertExists(page); assertExists(page);
const block = page.getBlockById(blockId) as ImageBlockModel; const block = page.getBlockById(blockId) as ImageBlockModel;
assertExists(block); assertExists(block);
return props.workspace.blob.get(block?.sourceId as string); return props.docCollection.blob.get(block?.sourceId as string);
}, },
suspense: true, suspense: true,
} }
@@ -508,7 +508,7 @@ export const ImagePreviewModal = (
return; return;
} }
const workspace = props.workspace; const workspace = props.docCollection;
const page = workspace.getDoc(props.pageId); const page = workspace.getDoc(props.pageId);
assertExists(page); assertExists(page);
@@ -541,7 +541,7 @@ export const ImagePreviewModal = (
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
}, },
[blockId, setBlockId, props.workspace, props.pageId, isOpen, setIsOpen] [blockId, setBlockId, props.docCollection, props.pageId, isOpen, setIsOpen]
); );
useEffect(() => { useEffect(() => {

View File

@@ -1,9 +1,9 @@
import './page-detail-editor.css'; import './page-detail-editor.css';
import { useBlockSuiteWorkspacePage } from '@affine/core/hooks/use-block-suite-workspace-page'; import { useDocCollectionPage } from '@affine/core/hooks/use-block-suite-workspace-page';
import { assertExists, DisposableGroup } from '@blocksuite/global/utils'; import { assertExists, DisposableGroup } from '@blocksuite/global/utils';
import type { AffineEditorContainer } from '@blocksuite/presets'; import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { Doc as BlockSuiteDoc } from '@blocksuite/store'; import type { Doc as BlockSuiteDoc } from '@blocksuite/store';
import { import {
Doc, Doc,
@@ -34,7 +34,7 @@ export type OnLoadEditor = (
export interface PageDetailEditorProps { export interface PageDetailEditorProps {
isPublic?: boolean; isPublic?: boolean;
publishMode?: PageMode; publishMode?: PageMode;
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
onLoad?: OnLoadEditor; onLoad?: OnLoadEditor;
} }
@@ -78,7 +78,7 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({
const disposableGroup = new DisposableGroup(); const disposableGroup = new DisposableGroup();
disposableGroup.add( disposableGroup.add(
page.slots.blockUpdated.once(() => { page.slots.blockUpdated.once(() => {
page.workspace.setDocMeta(page.id, { page.collection.setDocMeta(page.id, {
updatedDate: Date.now(), updatedDate: Date.now(),
}); });
}) })
@@ -121,8 +121,8 @@ const PageDetailEditorMain = memo(function PageDetailEditorMain({
}); });
export const PageDetailEditor = (props: PageDetailEditorProps) => { export const PageDetailEditor = (props: PageDetailEditorProps) => {
const { workspace, pageId } = props; const { docCollection, pageId } = props;
const page = useBlockSuiteWorkspacePage(workspace, pageId); const page = useDocCollectionPage(docCollection, pageId);
if (!page) { if (!page) {
return null; return null;
} }

View File

@@ -6,21 +6,21 @@ import 'fake-indexeddb/auto';
import { AffineSchemas } from '@blocksuite/blocks/schemas'; import { AffineSchemas } from '@blocksuite/blocks/schemas';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import { Schema, Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import { DocCollection, Schema } from '@blocksuite/store';
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import { describe, expect, test, vi } from 'vitest'; import { describe, expect, test, vi } from 'vitest';
import { beforeEach } from 'vitest'; import { beforeEach } from 'vitest';
import { useBlockSuitePagePreview } from '../use-block-suite-page-preview'; import { useBlockSuitePagePreview } from '../use-block-suite-page-preview';
let blockSuiteWorkspace: BlockSuiteWorkspace; let docCollection: DocCollection;
const schema = new Schema(); const schema = new Schema();
schema.register(AffineSchemas); schema.register(AffineSchemas);
beforeEach(async () => { beforeEach(async () => {
vi.useFakeTimers({ toFake: ['requestIdleCallback'] }); vi.useFakeTimers({ toFake: ['requestIdleCallback'] });
blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test', schema }); docCollection = new DocCollection({ id: 'test', schema });
const initPage = async (page: Doc) => { const initPage = async (page: Doc) => {
page.load(); page.load();
expect(page).not.toBeNull(); expect(page).not.toBeNull();
@@ -31,12 +31,12 @@ beforeEach(async () => {
const frameId = page.addBlock('affine:note', {}, pageBlockId); const frameId = page.addBlock('affine:note', {}, pageBlockId);
page.addBlock('affine:paragraph', {}, frameId); page.addBlock('affine:paragraph', {}, frameId);
}; };
await initPage(blockSuiteWorkspace.createDoc({ id: 'page0' })); await initPage(docCollection.createDoc({ id: 'page0' }));
}); });
describe('useBlockSuitePagePreview', () => { describe('useBlockSuitePagePreview', () => {
test('basic', async () => { test('basic', async () => {
const page = blockSuiteWorkspace.getDoc('page0') as Doc; const page = docCollection.getDoc('page0') as Doc;
const id = page.addBlock( const id = page.addBlock(
'affine:paragraph', 'affine:paragraph',
{ {

View File

@@ -125,7 +125,7 @@ export const VirtualizedCollectionList = ({
items={collectionMetas} items={collectionMetas}
itemRenderer={collectionItemRenderer} itemRenderer={collectionItemRenderer}
rowAsLink rowAsLink
blockSuiteWorkspace={currentWorkspace.blockSuiteWorkspace} docCollection={currentWorkspace.docCollection}
operationsRenderer={collectionOperationRenderer} operationsRenderer={collectionOperationRenderer}
headerRenderer={collectionHeaderRenderer} headerRenderer={collectionHeaderRenderer}
/> />

View File

@@ -18,7 +18,7 @@ export const PageListNewPageButton = ({
}>) => { }>) => {
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const { importFile, createEdgeless, createPage } = usePageHelper( const { importFile, createEdgeless, createPage } = usePageHelper(
currentWorkspace.blockSuiteWorkspace currentWorkspace.docCollection
); );
return ( return (
<div className={className} data-testid={testId}> <div className={className} data-testid={testId}>

View File

@@ -28,11 +28,9 @@ import {
const usePageOperationsRenderer = () => { const usePageOperationsRenderer = () => {
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const { setTrashModal } = useTrashModalHelper( const { setTrashModal } = useTrashModalHelper(currentWorkspace.docCollection);
currentWorkspace.blockSuiteWorkspace
);
const { toggleFavorite, duplicate } = useBlockSuiteMetaHelper( const { toggleFavorite, duplicate } = useBlockSuiteMetaHelper(
currentWorkspace.blockSuiteWorkspace currentWorkspace.docCollection
); );
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
@@ -97,11 +95,9 @@ export const VirtualizedPageList = ({
const [showFloatingToolbar, setShowFloatingToolbar] = useState(false); const [showFloatingToolbar, setShowFloatingToolbar] = useState(false);
const [selectedPageIds, setSelectedPageIds] = useState<string[]>([]); const [selectedPageIds, setSelectedPageIds] = useState<string[]>([]);
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const pageMetas = useBlockSuiteDocMeta(currentWorkspace.blockSuiteWorkspace); const pageMetas = useBlockSuiteDocMeta(currentWorkspace.docCollection);
const pageOperations = usePageOperationsRenderer(); const pageOperations = usePageOperationsRenderer();
const { isPreferredEdgeless } = usePageHelper( const { isPreferredEdgeless } = usePageHelper(currentWorkspace.docCollection);
currentWorkspace.blockSuiteWorkspace
);
const filteredPageMetas = useFilteredPageMetas(currentWorkspace, pageMetas, { const filteredPageMetas = useFilteredPageMetas(currentWorkspace, pageMetas, {
filters, filters,
@@ -155,9 +151,7 @@ export const VirtualizedPageList = ({
return <PageListHeader />; return <PageListHeader />;
}, [collection, config, currentWorkspace.id, tag]); }, [collection, config, currentWorkspace.id, tag]);
const { setTrashModal } = useTrashModalHelper( const { setTrashModal } = useTrashModalHelper(currentWorkspace.docCollection);
currentWorkspace.blockSuiteWorkspace
);
const handleMultiDelete = useCallback(() => { const handleMultiDelete = useCallback(() => {
const pageNameMapping = Object.fromEntries( const pageNameMapping = Object.fromEntries(
@@ -190,7 +184,7 @@ export const VirtualizedPageList = ({
items={pageMetasToRender} items={pageMetasToRender}
rowAsLink rowAsLink
isPreferredEdgeless={isPreferredEdgeless} isPreferredEdgeless={isPreferredEdgeless}
blockSuiteWorkspace={currentWorkspace.blockSuiteWorkspace} docCollection={currentWorkspace.docCollection}
operationsRenderer={pageOperationRenderer} operationsRenderer={pageOperationRenderer}
itemRenderer={pageItemRenderer} itemRenderer={pageItemRenderer}
headerRenderer={pageHeaderRenderer} headerRenderer={pageHeaderRenderer}

View File

@@ -1,31 +1,34 @@
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import { Suspense } from 'react'; import { Suspense } from 'react';
import { useBlockSuitePagePreview } from './use-block-suite-page-preview'; import { useBlockSuitePagePreview } from './use-block-suite-page-preview';
import { useBlockSuiteWorkspacePage } from './use-block-suite-workspace-page'; import { useDocCollectionPage } from './use-block-suite-workspace-page';
interface PagePreviewInnerProps { interface PagePreviewInnerProps {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
} }
const PagePreviewInner = ({ workspace, pageId }: PagePreviewInnerProps) => { const PagePreviewInner = ({
const page = useBlockSuiteWorkspacePage(workspace, pageId); docCollection: workspace,
pageId,
}: PagePreviewInnerProps) => {
const page = useDocCollectionPage(workspace, pageId);
const previewAtom = useBlockSuitePagePreview(page); const previewAtom = useBlockSuitePagePreview(page);
const preview = useAtomValue(previewAtom); const preview = useAtomValue(previewAtom);
return preview ? preview : null; return preview ? preview : null;
}; };
interface PagePreviewProps { interface PagePreviewProps {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
} }
export const PagePreview = ({ workspace, pageId }: PagePreviewProps) => { export const PagePreview = ({ docCollection, pageId }: PagePreviewProps) => {
return ( return (
<Suspense> <Suspense>
<PagePreviewInner workspace={workspace} pageId={pageId} /> <PagePreviewInner docCollection={docCollection} pageId={pageId} />
</Suspense> </Suspense>
); );
}; };

View File

@@ -9,7 +9,7 @@ import {
ToggleCollapseIcon, ToggleCollapseIcon,
ViewLayersIcon, ViewLayersIcon,
} from '@blocksuite/icons'; } from '@blocksuite/icons';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import { useService } from '@toeverything/infra'; import { useService } from '@toeverything/infra';
import { useLiveData } from '@toeverything/infra'; import { useLiveData } from '@toeverything/infra';
@@ -196,7 +196,7 @@ export const ItemGroup = <T extends ListItem>({
// todo: optimize how to render page meta list item // todo: optimize how to render page meta list item
const requiredPropNames = [ const requiredPropNames = [
'blockSuiteWorkspace', 'docCollection',
'rowAsLink', 'rowAsLink',
'isPreferredEdgeless', 'isPreferredEdgeless',
'operationsRenderer', 'operationsRenderer',
@@ -266,9 +266,9 @@ export const TagListItemRenderer = (item: ListItem) => {
function tagIdToTagOption( function tagIdToTagOption(
tagId: string, tagId: string,
blockSuiteWorkspace: Workspace docCollection: DocCollection
): Tag | undefined { ): Tag | undefined {
return blockSuiteWorkspace.meta.properties.tags?.options.find( return docCollection.meta.properties.tags?.options.find(
opt => opt.id === tagId opt => opt.id === tagId
); );
} }
@@ -286,15 +286,15 @@ const PageTitle = ({ id }: { id: string }) => {
const UnifiedPageIcon = ({ const UnifiedPageIcon = ({
id, id,
workspace, docCollection,
isPreferredEdgeless, isPreferredEdgeless,
}: { }: {
id: string; id: string;
workspace: Workspace; docCollection: DocCollection;
isPreferredEdgeless?: (id: string) => boolean; isPreferredEdgeless?: (id: string) => boolean;
}) => { }) => {
const isEdgeless = isPreferredEdgeless ? isPreferredEdgeless(id) : false; const isEdgeless = isPreferredEdgeless ? isPreferredEdgeless(id) : false;
const { isJournal } = useJournalInfoHelper(workspace, id); const { isJournal } = useJournalInfoHelper(docCollection, id);
if (isJournal) { if (isJournal) {
return <TodayIcon />; return <TodayIcon />;
} }
@@ -325,7 +325,7 @@ function pageMetaToListItemProp(
pageId: item.id, pageId: item.id,
title: <PageTitle id={item.id} />, title: <PageTitle id={item.id} />,
preview: ( preview: (
<PagePreview workspace={props.blockSuiteWorkspace} pageId={item.id} /> <PagePreview docCollection={props.docCollection} pageId={item.id} />
), ),
createDate: new Date(item.createDate), createDate: new Date(item.createDate),
updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined, updatedDate: item.updatedDate ? new Date(item.updatedDate) : undefined,
@@ -334,13 +334,13 @@ function pageMetaToListItemProp(
icon: ( icon: (
<UnifiedPageIcon <UnifiedPageIcon
id={item.id} id={item.id}
workspace={props.blockSuiteWorkspace} docCollection={props.docCollection}
isPreferredEdgeless={props.isPreferredEdgeless} isPreferredEdgeless={props.isPreferredEdgeless}
/> />
), ),
tags: tags:
item.tags item.tags
?.map(id => tagIdToTagOption(id, props.blockSuiteWorkspace)) ?.map(id => tagIdToTagOption(id, props.docCollection))
.filter((v): v is Tag => v != null) ?? [], .filter((v): v is Tag => v != null) ?? [],
operations: props.operationsRenderer?.(item), operations: props.operationsRenderer?.(item),
selectable: props.selectable, selectable: props.selectable,

View File

@@ -98,7 +98,7 @@ export const VirtualizedTagList = ({
items={tagMetas} items={tagMetas}
itemRenderer={tagItemRenderer} itemRenderer={tagItemRenderer}
rowAsLink rowAsLink
blockSuiteWorkspace={currentWorkspace.blockSuiteWorkspace} docCollection={currentWorkspace.docCollection}
operationsRenderer={tagOperationRenderer} operationsRenderer={tagOperationRenderer}
headerRenderer={tagHeaderRenderer} headerRenderer={tagHeaderRenderer}
/> />

View File

@@ -1,5 +1,5 @@
import type { Collection, Tag } from '@affine/env/filter'; import type { Collection, Tag } from '@affine/env/filter';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import type { PropsWithChildren, ReactNode } from 'react'; import type { PropsWithChildren, ReactNode } from 'react';
import type { To } from 'react-router-dom'; import type { To } from 'react-router-dom';
@@ -86,7 +86,7 @@ export type DateKey = 'createDate' | 'updatedDate';
export interface ListProps<T> { export interface ListProps<T> {
// required data: // required data:
items: T[]; items: T[];
blockSuiteWorkspace: Workspace; docCollection: DocCollection;
className?: string; className?: string;
hideHeader?: boolean; // whether or not to hide the header. default is false (showing header) hideHeader?: boolean; // whether or not to hide the header. default is false (showing header)
groupBy?: ItemGroupByType | false; groupBy?: ItemGroupByType | false;

View File

@@ -1,29 +1,29 @@
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import { DisposableGroup } from '@blocksuite/global/utils'; import { DisposableGroup } from '@blocksuite/global/utils';
import type { Doc, Workspace } from '@blocksuite/store'; import type { Doc, DocCollection } from '@blocksuite/store';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
const logger = new DebugLogger('useBlockSuiteWorkspacePage'); const logger = new DebugLogger('useBlockSuiteWorkspacePage');
export function useBlockSuiteWorkspacePage( export function useDocCollectionPage(
blockSuiteWorkspace: Workspace, docCollection: DocCollection,
pageId: string | null pageId: string | null
): Doc | null { ): Doc | null {
const [page, setPage] = useState( const [page, setPage] = useState(
pageId ? blockSuiteWorkspace.getDoc(pageId) : null pageId ? docCollection.getDoc(pageId) : null
); );
useEffect(() => { useEffect(() => {
const group = new DisposableGroup(); const group = new DisposableGroup();
group.add( group.add(
blockSuiteWorkspace.slots.docAdded.on(id => { docCollection.slots.docAdded.on(id => {
if (pageId === id) { if (pageId === id) {
setPage(blockSuiteWorkspace.getDoc(id)); setPage(docCollection.getDoc(id));
} }
}) })
); );
group.add( group.add(
blockSuiteWorkspace.slots.docRemoved.on(id => { docCollection.slots.docRemoved.on(id => {
if (pageId === id) { if (pageId === id) {
setPage(null); setPage(null);
} }
@@ -32,7 +32,7 @@ export function useBlockSuiteWorkspacePage(
return () => { return () => {
group.dispose(); group.dispose();
}; };
}, [blockSuiteWorkspace, pageId]); }, [docCollection, pageId]);
useEffect(() => { useEffect(() => {
if (page && !page.loaded) { if (page && !page.loaded) {
@@ -46,9 +46,9 @@ export function useBlockSuiteWorkspacePage(
useEffect(() => { useEffect(() => {
if (page?.id !== pageId) { if (page?.id !== pageId) {
setPage(pageId ? blockSuiteWorkspace.getDoc(pageId) : null); setPage(pageId ? docCollection.getDoc(pageId) : null);
} }
}, [blockSuiteWorkspace, page?.id, pageId]); }, [docCollection, page?.id, pageId]);
return page; return page;
} }

View File

@@ -6,7 +6,7 @@ import {
} from '@affine/component'; } from '@affine/component';
import type { Collection } from '@affine/env/filter'; import type { Collection } from '@affine/env/filter';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import type { DialogContentProps } from '@radix-ui/react-dialog'; import type { DialogContentProps } from '@radix-ui/react-dialog';
import { type ReactNode, useCallback, useMemo, useState } from 'react'; import { type ReactNode, useCallback, useMemo, useState } from 'react';
@@ -199,7 +199,7 @@ export const EditCollection = ({
export type AllPageListConfig = { export type AllPageListConfig = {
allPages: DocMeta[]; allPages: DocMeta[];
workspace: Workspace; docCollection: DocCollection;
isEdgeless: (id: string) => boolean; isEdgeless: (id: string) => boolean;
/** /**
* Return `undefined` if the page is not public * Return `undefined` if the page is not public

View File

@@ -87,7 +87,9 @@ export const PagesMode = ({
<Menu <Menu
items={ items={
<VariableSelect <VariableSelect
propertiesMeta={allPageListConfig.workspace.meta.properties} propertiesMeta={
allPageListConfig.docCollection.meta.properties
}
selected={filters} selected={filters}
onSelect={createFilter} onSelect={createFilter}
/> />
@@ -114,7 +116,7 @@ export const PagesMode = ({
{showFilter ? ( {showFilter ? (
<div style={{ padding: '12px 16px 16px' }}> <div style={{ padding: '12px 16px 16px' }}>
<FilterList <FilterList
propertiesMeta={allPageListConfig.workspace.meta.properties} propertiesMeta={allPageListConfig.docCollection.meta.properties}
value={filters} value={filters}
onChange={updateFilters} onChange={updateFilters}
/> />
@@ -125,7 +127,7 @@ export const PagesMode = ({
className={styles.pageList} className={styles.pageList}
items={searchedList} items={searchedList}
groupBy={false} groupBy={false}
blockSuiteWorkspace={allPageListConfig.workspace} docCollection={allPageListConfig.docCollection}
selectable selectable
onSelectedIdsChange={ids => { onSelectedIdsChange={ids => {
updateCollection({ updateCollection({

View File

@@ -123,7 +123,7 @@ export const RulesMode = ({
}} }}
> >
<FilterList <FilterList
propertiesMeta={allPageListConfig.workspace.meta.properties} propertiesMeta={allPageListConfig.docCollection.meta.properties}
value={collection.filterList} value={collection.filterList}
onChange={useCallback( onChange={useCallback(
filterList => updateCollection({ ...collection, filterList }), filterList => updateCollection({ ...collection, filterList }),
@@ -265,7 +265,7 @@ export const RulesMode = ({
className={styles.resultPages} className={styles.resultPages}
items={rulesPages} items={rulesPages}
groupBy={false} groupBy={false}
blockSuiteWorkspace={allPageListConfig.workspace} docCollection={allPageListConfig.docCollection}
isPreferredEdgeless={allPageListConfig.isEdgeless} isPreferredEdgeless={allPageListConfig.isEdgeless}
operationsRenderer={operationsRenderer} operationsRenderer={operationsRenderer}
></List> ></List>
@@ -285,7 +285,7 @@ export const RulesMode = ({
className={styles.resultPages} className={styles.resultPages}
items={allowListPages} items={allowListPages}
groupBy={false} groupBy={false}
blockSuiteWorkspace={allPageListConfig.workspace} docCollection={allPageListConfig.docCollection}
isPreferredEdgeless={allPageListConfig.isEdgeless} isPreferredEdgeless={allPageListConfig.isEdgeless}
operationsRenderer={operationsRenderer} operationsRenderer={operationsRenderer}
></List> ></List>

View File

@@ -76,7 +76,9 @@ export const SelectPage = ({
<Menu <Menu
items={ items={
<VariableSelect <VariableSelect
propertiesMeta={allPageListConfig.workspace.meta.properties} propertiesMeta={
allPageListConfig.docCollection.meta.properties
}
selected={filters} selected={filters}
onSelect={createFilter} onSelect={createFilter}
/> />
@@ -103,7 +105,7 @@ export const SelectPage = ({
{showFilter ? ( {showFilter ? (
<div style={{ padding: '12px 16px 16px' }}> <div style={{ padding: '12px 16px 16px' }}>
<FilterList <FilterList
propertiesMeta={allPageListConfig.workspace.meta.properties} propertiesMeta={allPageListConfig.docCollection.meta.properties}
value={filters} value={filters}
onChange={updateFilters} onChange={updateFilters}
/> />
@@ -113,7 +115,7 @@ export const SelectPage = ({
<VirtualizedList <VirtualizedList
className={styles.pageList} className={styles.pageList}
items={searchedList} items={searchedList}
blockSuiteWorkspace={allPageListConfig.workspace} docCollection={allPageListConfig.docCollection}
selectable selectable
groupBy={false} groupBy={false}
onSelectedIdsChange={onChange} onSelectedIdsChange={onChange}

View File

@@ -2,7 +2,7 @@ import {
useBlockSuiteDocMeta, useBlockSuiteDocMeta,
useDocMetaHelper, useDocMetaHelper,
} from '@affine/core/hooks/use-block-suite-page-meta'; } from '@affine/core/hooks/use-block-suite-page-meta';
import { useGetBlockSuiteWorkspacePageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title'; import { useGetDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
import { useJournalHelper } from '@affine/core/hooks/use-journal'; import { useJournalHelper } from '@affine/core/hooks/use-journal';
import { CollectionService } from '@affine/core/modules/collection'; import { CollectionService } from '@affine/core/modules/collection';
import { WorkspaceSubPath } from '@affine/core/shared'; import { WorkspaceSubPath } from '@affine/core/shared';
@@ -79,7 +79,7 @@ function getAllCommand(context: CommandContext) {
const useWorkspacePages = () => { const useWorkspacePages = () => {
const workspace = useService(Workspace); const workspace = useService(Workspace);
const pages = useBlockSuiteDocMeta(workspace.blockSuiteWorkspace); const pages = useBlockSuiteDocMeta(workspace.docCollection);
return pages; return pages;
}; };
@@ -100,7 +100,7 @@ export const pageToCommand = (
category: CommandCategory, category: CommandCategory,
page: DocMeta, page: DocMeta,
navigationHelper: ReturnType<typeof useNavigateHelper>, navigationHelper: ReturnType<typeof useNavigateHelper>,
getPageTitle: ReturnType<typeof useGetBlockSuiteWorkspacePageTitle>, getPageTitle: ReturnType<typeof useGetDocCollectionPageTitle>,
isPageJournal: (pageId: string) => boolean, isPageJournal: (pageId: string) => boolean,
t: ReturnType<typeof useAFFiNEI18N>, t: ReturnType<typeof useAFFiNEI18N>,
workspace: Workspace, workspace: Workspace,
@@ -151,16 +151,14 @@ export const usePageCommands = () => {
const recentPages = useRecentPages(); const recentPages = useRecentPages();
const pages = useWorkspacePages(); const pages = useWorkspacePages();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const pageHelper = usePageHelper(workspace.blockSuiteWorkspace); const pageHelper = usePageHelper(workspace.docCollection);
const pageMetaHelper = useDocMetaHelper(workspace.blockSuiteWorkspace); const pageMetaHelper = useDocMetaHelper(workspace.docCollection);
const query = useAtomValue(cmdkQueryAtom); const query = useAtomValue(cmdkQueryAtom);
const navigationHelper = useNavigateHelper(); const navigationHelper = useNavigateHelper();
const journalHelper = useJournalHelper(workspace.blockSuiteWorkspace); const journalHelper = useJournalHelper(workspace.docCollection);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const getPageTitle = useGetBlockSuiteWorkspacePageTitle( const getPageTitle = useGetDocCollectionPageTitle(workspace.docCollection);
workspace.blockSuiteWorkspace const { isPageJournal } = useJournalHelper(workspace.docCollection);
);
const { isPageJournal } = useJournalHelper(workspace.blockSuiteWorkspace);
const [searchTime, setSearchTime] = useState<number>(0); const [searchTime, setSearchTime] = useState<number>(0);
@@ -197,7 +195,7 @@ export const usePageCommands = () => {
} else { } else {
// queried pages that has matched contents // queried pages that has matched contents
// TODO: we shall have a debounce for global search here // TODO: we shall have a debounce for global search here
const searchResults = workspace.blockSuiteWorkspace.search({ const searchResults = workspace.docCollection.search({
query, query,
}) as unknown as Map<string, SearchResultsValue>; }) as unknown as Map<string, SearchResultsValue>;
const resultValues = Array.from(searchResults.values()); const resultValues = Array.from(searchResults.values());
@@ -242,7 +240,7 @@ export const usePageCommands = () => {
if (!appendRes) return; if (!appendRes) return;
const { page, blockId } = appendRes; const { page, blockId } = appendRes;
navigationHelper.jumpToPageBlock( navigationHelper.jumpToPageBlock(
page.workspace.id, page.collection.id,
page.id, page.id,
blockId blockId
); );

View File

@@ -22,15 +22,15 @@ export const TrashPageFooter = ({ pageId }: { pageId: string }) => {
useService(CurrentWorkspaceService).currentWorkspace useService(CurrentWorkspaceService).currentWorkspace
); );
assertExists(workspace); assertExists(workspace);
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const pageMeta = useBlockSuiteDocMeta(blockSuiteWorkspace).find( const pageMeta = useBlockSuiteDocMeta(docCollection).find(
meta => meta.id === pageId meta => meta.id === pageId
); );
assertExists(pageMeta); assertExists(pageMeta);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const { appSettings } = useAppSettingHelper(); const { appSettings } = useAppSettingHelper();
const { jumpToSubPath } = useNavigateHelper(); const { jumpToSubPath } = useNavigateHelper();
const { restoreFromTrash } = useBlockSuiteMetaHelper(blockSuiteWorkspace); const { restoreFromTrash } = useBlockSuiteMetaHelper(docCollection);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const hintText = t['com.affine.cmdk.affine.editor.trash-footer-hint'](); const hintText = t['com.affine.cmdk.affine.editor.trash-footer-hint']();
@@ -45,9 +45,9 @@ export const TrashPageFooter = ({ pageId }: { pageId: string }) => {
const onConfirmDelete = useCallback(() => { const onConfirmDelete = useCallback(() => {
jumpToSubPath(workspace.id, WorkspaceSubPath.ALL); jumpToSubPath(workspace.id, WorkspaceSubPath.ALL);
blockSuiteWorkspace.removeDoc(pageId); docCollection.removeDoc(pageId);
toast(t['com.affine.toastMessage.permanentlyDeleted']()); toast(t['com.affine.toastMessage.permanentlyDeleted']());
}, [blockSuiteWorkspace, jumpToSubPath, pageId, workspace.id, t]); }, [docCollection, jumpToSubPath, pageId, workspace.id, t]);
const onDelete = useCallback(() => { const onDelete = useCallback(() => {
setOpen(true); setOpen(true);

View File

@@ -10,7 +10,7 @@ import { CollectionService } from '@affine/core/modules/collection';
import type { Collection, DeleteCollectionInfo } from '@affine/env/filter'; import type { Collection, DeleteCollectionInfo } from '@affine/env/filter';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { MoreHorizontalIcon, ViewLayersIcon } from '@blocksuite/icons'; import { MoreHorizontalIcon, ViewLayersIcon } from '@blocksuite/icons';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import { useDroppable } from '@dnd-kit/core'; import { useDroppable } from '@dnd-kit/core';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import { useService } from '@toeverything/infra'; import { useService } from '@toeverything/infra';
@@ -30,12 +30,12 @@ import * as styles from './styles.css';
const CollectionRenderer = ({ const CollectionRenderer = ({
collection, collection,
pages, pages,
workspace, docCollection,
info, info,
}: { }: {
collection: Collection; collection: Collection;
pages: DocMeta[]; pages: DocMeta[];
workspace: Workspace; docCollection: DocCollection;
info: DeleteCollectionInfo; info: DeleteCollectionInfo;
}) => { }) => {
const [collapsed, setCollapsed] = useState(true); const [collapsed, setCollapsed] = useState(true);
@@ -159,7 +159,7 @@ const CollectionRenderer = ({
allPageMeta={allPagesMeta} allPageMeta={allPagesMeta}
page={page} page={page}
key={page.id} key={page.id}
workspace={workspace} docCollection={docCollection}
/> />
); );
})} })}
@@ -169,7 +169,7 @@ const CollectionRenderer = ({
); );
}; };
export const CollectionsList = ({ export const CollectionsList = ({
workspace, docCollection: workspace,
info, info,
onCreate, onCreate,
}: CollectionsListProps) => { }: CollectionsListProps) => {
@@ -205,7 +205,7 @@ export const CollectionsList = ({
key={view.id} key={view.id}
collection={view} collection={view}
pages={metas} pages={metas}
workspace={workspace} docCollection={workspace}
/> />
); );
})} })}

View File

@@ -1,7 +1,7 @@
import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references'; import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import { useDraggable } from '@dnd-kit/core'; import { useDraggable } from '@dnd-kit/core';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import { PageRecordList, useLiveData, useService } from '@toeverything/infra'; import { PageRecordList, useLiveData, useService } from '@toeverything/infra';
@@ -18,7 +18,7 @@ import * as styles from './styles.css';
export const Page = ({ export const Page = ({
page, page,
workspace, docCollection,
allPageMeta, allPageMeta,
inAllowList, inAllowList,
removeFromAllowList, removeFromAllowList,
@@ -26,7 +26,7 @@ export const Page = ({
page: DocMeta; page: DocMeta;
inAllowList: boolean; inAllowList: boolean;
removeFromAllowList: (id: string) => void; removeFromAllowList: (id: string) => void;
workspace: Workspace; docCollection: DocCollection;
allPageMeta: Record<string, DocMeta>; allPageMeta: Record<string, DocMeta>;
}) => { }) => {
const [collapsed, setCollapsed] = React.useState(true); const [collapsed, setCollapsed] = React.useState(true);
@@ -46,10 +46,10 @@ export const Page = ({
const { jumpToPage } = useNavigateHelper(); const { jumpToPage } = useNavigateHelper();
const clickPage = useCallback(() => { const clickPage = useCallback(() => {
jumpToPage(workspace.id, page.id); jumpToPage(docCollection.id, page.id);
}, [jumpToPage, page.id, workspace.id]); }, [jumpToPage, page.id, docCollection.id]);
const references = useBlockSuitePageReferences(workspace, pageId); const references = useBlockSuitePageReferences(docCollection, pageId);
const referencesToRender = references.filter( const referencesToRender = references.filter(
id => allPageMeta[id] && !allPageMeta[id]?.trash id => allPageMeta[id] && !allPageMeta[id]?.trash
); );
@@ -85,7 +85,7 @@ export const Page = ({
onCollapsedChange={setCollapsed} onCollapsedChange={setCollapsed}
postfix={ postfix={
<PostfixItem <PostfixItem
workspace={workspace} docCollection={docCollection}
pageId={pageId} pageId={pageId}
pageTitle={pageTitle} pageTitle={pageTitle}
removeFromAllowList={removeFromAllowList} removeFromAllowList={removeFromAllowList}
@@ -103,7 +103,7 @@ export const Page = ({
return ( return (
<ReferencePage <ReferencePage
key={id} key={id}
workspace={workspace} docCollection={docCollection}
pageId={id} pageId={id}
metaMapping={allPageMeta} metaMapping={allPageMeta}
parentIds={new Set([pageId])} parentIds={new Set([pageId])}

View File

@@ -3,7 +3,7 @@ import { IconButton } from '@affine/component/ui/button';
import { Menu } from '@affine/component/ui/menu'; import { Menu } from '@affine/component/ui/menu';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { MoreHorizontalIcon } from '@blocksuite/icons'; import { MoreHorizontalIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useBlockSuiteMetaHelper } from '../../../../hooks/affine/use-block-suite-meta-helper'; import { useBlockSuiteMetaHelper } from '../../../../hooks/affine/use-block-suite-meta-helper';
@@ -13,7 +13,7 @@ import { OperationItems } from './operation-item';
export type OperationMenuButtonProps = { export type OperationMenuButtonProps = {
pageId: string; pageId: string;
workspace: Workspace; docCollection: DocCollection;
pageTitle: string; pageTitle: string;
setRenameModalOpen: () => void; setRenameModalOpen: () => void;
inFavorites?: boolean; inFavorites?: boolean;
@@ -24,7 +24,7 @@ export type OperationMenuButtonProps = {
export const OperationMenuButton = ({ ...props }: OperationMenuButtonProps) => { export const OperationMenuButton = ({ ...props }: OperationMenuButtonProps) => {
const { const {
workspace, docCollection,
pageId, pageId,
pageTitle, pageTitle,
setRenameModalOpen, setRenameModalOpen,
@@ -34,9 +34,9 @@ export const OperationMenuButton = ({ ...props }: OperationMenuButtonProps) => {
isReferencePage, isReferencePage,
} = props; } = props;
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const { createLinkedPage } = usePageHelper(workspace); const { createLinkedPage } = usePageHelper(docCollection);
const { setTrashModal } = useTrashModalHelper(workspace); const { setTrashModal } = useTrashModalHelper(docCollection);
const { removeFromFavorite } = useBlockSuiteMetaHelper(workspace); const { removeFromFavorite } = useBlockSuiteMetaHelper(docCollection);
const handleRename = useCallback(() => { const handleRename = useCallback(() => {
setRenameModalOpen?.(); setRenameModalOpen?.();

View File

@@ -2,7 +2,7 @@ import { toast } from '@affine/component';
import { RenameModal } from '@affine/component/rename-modal'; import { RenameModal } from '@affine/component/rename-modal';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { AddFavouriteButton } from '../favorite/add-favourite-button'; import { AddFavouriteButton } from '../favorite/add-favourite-button';
@@ -10,7 +10,7 @@ import * as styles from '../favorite/styles.css';
import { OperationMenuButton } from './operation-menu-button'; import { OperationMenuButton } from './operation-menu-button';
type PostfixItemProps = { type PostfixItemProps = {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
pageTitle: string; pageTitle: string;
inFavorites?: boolean; inFavorites?: boolean;
@@ -20,10 +20,10 @@ type PostfixItemProps = {
}; };
export const PostfixItem = ({ ...props }: PostfixItemProps) => { export const PostfixItem = ({ ...props }: PostfixItemProps) => {
const { workspace, pageId, pageTitle } = props; const { docCollection, pageId, pageTitle } = props;
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const { setDocTitle } = useDocMetaHelper(workspace); const { setDocTitle } = useDocMetaHelper(docCollection);
const handleRename = useCallback( const handleRename = useCallback(
(newName: string) => { (newName: string) => {

View File

@@ -1,7 +1,7 @@
import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references'; import { useBlockSuitePageReferences } from '@affine/core/hooks/use-block-suite-page-references';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { EdgelessIcon, PageIcon } from '@blocksuite/icons'; import { EdgelessIcon, PageIcon } from '@blocksuite/icons';
import { type DocMeta, type Workspace } from '@blocksuite/store'; import { type DocCollection, type DocMeta } from '@blocksuite/store';
import * as Collapsible from '@radix-ui/react-collapsible'; import * as Collapsible from '@radix-ui/react-collapsible';
import { PageRecordList, useLiveData, useService } from '@toeverything/infra'; import { PageRecordList, useLiveData, useService } from '@toeverything/infra';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
@@ -11,14 +11,14 @@ import { MenuLinkItem } from '../../../app-sidebar';
import * as styles from '../favorite/styles.css'; import * as styles from '../favorite/styles.css';
import { PostfixItem } from './postfix-item'; import { PostfixItem } from './postfix-item';
export interface ReferencePageProps { export interface ReferencePageProps {
workspace: Workspace; docCollection: DocCollection;
pageId: string; pageId: string;
metaMapping: Record<string, DocMeta>; metaMapping: Record<string, DocMeta>;
parentIds: Set<string>; parentIds: Set<string>;
} }
export const ReferencePage = ({ export const ReferencePage = ({
workspace, docCollection,
pageId, pageId,
metaMapping, metaMapping,
parentIds, parentIds,
@@ -33,7 +33,7 @@ export const ReferencePage = ({
return pageMode === 'edgeless' ? <EdgelessIcon /> : <PageIcon />; return pageMode === 'edgeless' ? <EdgelessIcon /> : <PageIcon />;
}, [pageMode]); }, [pageMode]);
const references = useBlockSuitePageReferences(workspace, pageId); const references = useBlockSuitePageReferences(docCollection, pageId);
const referencesToShow = useMemo(() => { const referencesToShow = useMemo(() => {
return [ return [
...new Set( ...new Set(
@@ -59,13 +59,13 @@ export const ReferencePage = ({
data-type="reference-page" data-type="reference-page"
data-testid={`reference-page-${pageId}`} data-testid={`reference-page-${pageId}`}
active={active} active={active}
to={`/workspace/${workspace.id}/${pageId}`} to={`/workspace/${docCollection.id}/${pageId}`}
icon={icon} icon={icon}
collapsed={collapsible ? collapsed : undefined} collapsed={collapsible ? collapsed : undefined}
onCollapsedChange={setCollapsed} onCollapsedChange={setCollapsed}
postfix={ postfix={
<PostfixItem <PostfixItem
workspace={workspace} docCollection={docCollection}
pageId={pageId} pageId={pageId}
pageTitle={pageTitle} pageTitle={pageTitle}
isReferencePage={true} isReferencePage={true}
@@ -83,7 +83,7 @@ export const ReferencePage = ({
return ( return (
<ReferencePage <ReferencePage
key={ref} key={ref}
workspace={workspace} docCollection={docCollection}
pageId={ref} pageId={ref}
metaMapping={metaMapping} metaMapping={metaMapping}
parentIds={new Set([...parentIds, pageId])} parentIds={new Set([...parentIds, pageId])}

View File

@@ -2,21 +2,21 @@ import { IconButton } from '@affine/component/ui/button';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { PlusIcon } from '@blocksuite/icons'; import { PlusIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { usePageHelper } from '../../../blocksuite/block-suite-page-list/utils'; import { usePageHelper } from '../../../blocksuite/block-suite-page-list/utils';
type AddFavouriteButtonProps = { type AddFavouriteButtonProps = {
workspace: Workspace; docCollection: DocCollection;
pageId?: string; pageId?: string;
}; };
export const AddFavouriteButton = ({ export const AddFavouriteButton = ({
workspace, docCollection,
pageId, pageId,
}: AddFavouriteButtonProps) => { }: AddFavouriteButtonProps) => {
const { createPage, createLinkedPage } = usePageHelper(workspace); const { createPage, createLinkedPage } = usePageHelper(docCollection);
const { setDocMeta } = useDocMetaHelper(workspace); const { setDocMeta } = useDocMetaHelper(docCollection);
const handleAddFavorite = useAsyncCallback( const handleAddFavorite = useAsyncCallback(
async e => { async e => {
if (pageId) { if (pageId) {

View File

@@ -11,7 +11,9 @@ import * as styles from './styles.css';
const emptyPageIdSet = new Set<string>(); const emptyPageIdSet = new Set<string>();
export const FavoriteList = ({ workspace }: FavoriteListProps) => { export const FavoriteList = ({
docCollection: workspace,
}: FavoriteListProps) => {
const metas = useBlockSuiteDocMeta(workspace); const metas = useBlockSuiteDocMeta(workspace);
const dropItemId = getDropItemId('favorites'); const dropItemId = getDropItemId('favorites');
@@ -51,7 +53,7 @@ export const FavoriteList = ({ workspace }: FavoriteListProps) => {
pageId={pageMeta.id} pageId={pageMeta.id}
// memo? // memo?
parentIds={emptyPageIdSet} parentIds={emptyPageIdSet}
workspace={workspace} docCollection={workspace}
/> />
); );
})} })}

View File

@@ -20,7 +20,7 @@ import {
import * as styles from './styles.css'; import * as styles from './styles.css';
export const FavouritePage = ({ export const FavouritePage = ({
workspace, docCollection: workspace,
pageId, pageId,
metaMapping, metaMapping,
parentIds, parentIds,
@@ -86,7 +86,7 @@ export const FavouritePage = ({
{...listeners} {...listeners}
postfix={ postfix={
<PostfixItem <PostfixItem
workspace={workspace} docCollection={workspace}
pageId={pageId} pageId={pageId}
pageTitle={pageTitle} pageTitle={pageTitle}
inFavorites={true} inFavorites={true}
@@ -102,7 +102,7 @@ export const FavouritePage = ({
return ( return (
<ReferencePage <ReferencePage
key={id} key={id}
workspace={workspace} docCollection={workspace}
pageId={id} pageId={id}
metaMapping={metaMapping} metaMapping={metaMapping}
parentIds={new Set([pageId])} parentIds={new Set([pageId])}

View File

@@ -1,12 +1,12 @@
import type { DeleteCollectionInfo } from '@affine/env/filter'; import type { DeleteCollectionInfo } from '@affine/env/filter';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
export type FavoriteListProps = { export type FavoriteListProps = {
workspace: Workspace; docCollection: DocCollection;
}; };
export type CollectionsListProps = { export type CollectionsListProps = {
workspace: Workspace; docCollection: DocCollection;
info: DeleteCollectionInfo; info: DeleteCollectionInfo;
onCreate?: () => void; onCreate?: () => void;
}; };

View File

@@ -1,17 +1,13 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { ImportIcon } from '@blocksuite/icons'; import { ImportIcon } from '@blocksuite/icons';
import type { BlockSuiteWorkspace } from '../../shared'; import type { DocCollection } from '../../shared';
import { MenuItem } from '../app-sidebar'; import { MenuItem } from '../app-sidebar';
import { usePageHelper } from '../blocksuite/block-suite-page-list/utils'; import { usePageHelper } from '../blocksuite/block-suite-page-list/utils';
const ImportPage = ({ const ImportPage = ({ docCollection }: { docCollection: DocCollection }) => {
blocksuiteWorkspace,
}: {
blocksuiteWorkspace: BlockSuiteWorkspace;
}) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const { importFile } = usePageHelper(blocksuiteWorkspace); const { importFile } = usePageHelper(docCollection);
return ( return (
<MenuItem icon={<ImportIcon />} onClick={importFile}> <MenuItem icon={<ImportIcon />} onClick={importFile}>
{t['Import']()} {t['Import']()}

View File

@@ -100,7 +100,7 @@ export const RootAppSidebar = ({
}: RootAppSidebarProps): ReactElement => { }: RootAppSidebarProps): ReactElement => {
const currentWorkspaceId = currentWorkspace.id; const currentWorkspaceId = currentWorkspace.id;
const { appSettings } = useAppSettingHelper(); const { appSettings } = useAppSettingHelper();
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace; const docCollection = currentWorkspace.docCollection;
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const [openUserWorkspaceList, setOpenUserWorkspaceList] = useAtom( const [openUserWorkspaceList, setOpenUserWorkspaceList] = useAtom(
openWorkspaceListModalAtom openWorkspaceListModalAtom
@@ -114,7 +114,7 @@ export const RootAppSidebar = ({
}, [createPage, openPage]); }, [createPage, openPage]);
const { trashModal, setTrashModal, handleOnConfirm } = const { trashModal, setTrashModal, handleOnConfirm } =
useTrashModalHelper(blockSuiteWorkspace); useTrashModalHelper(docCollection);
const deletePageTitles = trashModal.pageTitles; const deletePageTitles = trashModal.pageTitles;
const trashConfirmOpen = trashModal.open; const trashConfirmOpen = trashModal.open;
const onTrashConfirmOpenChange = useCallback( const onTrashConfirmOpenChange = useCallback(
@@ -164,12 +164,12 @@ export const RootAppSidebar = ({
.then(name => { .then(name => {
const id = nanoid(); const id = nanoid();
collection.addCollection(createEmptyCollection(id, { name })); collection.addCollection(createEmptyCollection(id, { name }));
navigateHelper.jumpToCollection(blockSuiteWorkspace.id, id); navigateHelper.jumpToCollection(docCollection.id, id);
}) })
.catch(err => { .catch(err => {
console.error(err); console.error(err);
}); });
}, [blockSuiteWorkspace.id, collection, navigateHelper, open]); }, [docCollection.id, collection, navigateHelper, open]);
const allPageActive = currentPath === '/all'; const allPageActive = currentPath === '/all';
@@ -227,7 +227,7 @@ export const RootAppSidebar = ({
</span> </span>
</RouteMenuLinkItem> </RouteMenuLinkItem>
<AppSidebarJournalButton <AppSidebarJournalButton
workspace={currentWorkspace.blockSuiteWorkspace} docCollection={currentWorkspace.docCollection}
/> />
{runtimeConfig.enableNewSettingModal ? ( {runtimeConfig.enableNewSettingModal ? (
<MenuItem <MenuItem
@@ -244,14 +244,14 @@ export const RootAppSidebar = ({
<SidebarScrollableContainer> <SidebarScrollableContainer>
<CategoryDivider label={t['com.affine.rootAppSidebar.favorites']()}> <CategoryDivider label={t['com.affine.rootAppSidebar.favorites']()}>
<AddFavouriteButton workspace={blockSuiteWorkspace} /> <AddFavouriteButton docCollection={docCollection} />
</CategoryDivider> </CategoryDivider>
<FavoriteList workspace={blockSuiteWorkspace} /> <FavoriteList docCollection={docCollection} />
<CategoryDivider label={t['com.affine.rootAppSidebar.collections']()}> <CategoryDivider label={t['com.affine.rootAppSidebar.collections']()}>
<AddCollectionButton node={node} onClick={handleCreateCollection} /> <AddCollectionButton node={node} onClick={handleCreateCollection} />
</CategoryDivider> </CategoryDivider>
<CollectionsList <CollectionsList
workspace={blockSuiteWorkspace} docCollection={docCollection}
info={userInfo} info={userInfo}
onCreate={handleCreateCollection} onCreate={handleCreateCollection}
/> />
@@ -268,7 +268,7 @@ export const RootAppSidebar = ({
{t['com.affine.workspaceSubPath.trash']()} {t['com.affine.workspaceSubPath.trash']()}
</span> </span>
</RouteMenuLinkItem> </RouteMenuLinkItem>
<ImportPage blocksuiteWorkspace={blockSuiteWorkspace} /> <ImportPage docCollection={docCollection} />
</SidebarScrollableContainer> </SidebarScrollableContainer>
<SidebarContainer> <SidebarContainer>
{environment.isDesktop ? <UpdaterButton /> : <AppDownloadButton />} {environment.isDesktop ? <UpdaterButton /> : <AppDownloadButton />}

View File

@@ -2,7 +2,7 @@ import {
useJournalInfoHelper, useJournalInfoHelper,
useJournalRouteHelper, useJournalRouteHelper,
} from '@affine/core/hooks/use-journal'; } from '@affine/core/hooks/use-journal';
import type { BlockSuiteWorkspace } from '@affine/core/shared'; import type { DocCollection } from '@affine/core/shared';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { TodayIcon, TomorrowIcon, YesterdayIcon } from '@blocksuite/icons'; import { TodayIcon, TomorrowIcon, YesterdayIcon } from '@blocksuite/icons';
import { Doc, useServiceOptional } from '@toeverything/infra'; import { Doc, useServiceOptional } from '@toeverything/infra';
@@ -11,17 +11,17 @@ import { useParams } from 'react-router-dom';
import { MenuItem } from '../app-sidebar'; import { MenuItem } from '../app-sidebar';
interface AppSidebarJournalButtonProps { interface AppSidebarJournalButtonProps {
workspace: BlockSuiteWorkspace; docCollection: DocCollection;
} }
export const AppSidebarJournalButton = ({ export const AppSidebarJournalButton = ({
workspace, docCollection,
}: AppSidebarJournalButtonProps) => { }: AppSidebarJournalButtonProps) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const currentPage = useServiceOptional(Doc); const currentPage = useServiceOptional(Doc);
const { openToday } = useJournalRouteHelper(workspace); const { openToday } = useJournalRouteHelper(docCollection);
const { journalDate, isJournal } = useJournalInfoHelper( const { journalDate, isJournal } = useJournalInfoHelper(
workspace, docCollection,
currentPage?.id currentPage?.id
); );
const params = useParams(); const params = useParams();

View File

@@ -11,14 +11,14 @@ import type { PropsWithChildren } from 'react';
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
import { useBlockSuiteDocMeta } from '../use-block-suite-page-meta'; import { useBlockSuiteDocMeta } from '../use-block-suite-page-meta';
import { useBlockSuiteWorkspaceHelper } from '../use-block-suite-workspace-helper'; import { useDocCollectionHelper } from '../use-block-suite-workspace-helper';
const configureTestingWorkspace = async () => { const configureTestingWorkspace = async () => {
const { workspace } = await configureTestingEnvironment(); const { workspace } = await configureTestingEnvironment();
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
initEmptyPage(blockSuiteWorkspace.createDoc({ id: 'page1' })); initEmptyPage(docCollection.createDoc({ id: 'page1' }));
initEmptyPage(blockSuiteWorkspace.createDoc({ id: 'page2' })); initEmptyPage(docCollection.createDoc({ id: 'page2' }));
return workspace; return workspace;
}; };
@@ -36,31 +36,25 @@ const getWrapper = (workspace: Workspace) =>
); );
}; };
describe('useBlockSuiteWorkspaceHelper', () => { describe('useDocCollectionHelper', () => {
test('should create page', async () => { test('should create page', async () => {
const workspace = await configureTestingWorkspace(); const workspace = await configureTestingWorkspace();
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const Wrapper = getWrapper(workspace); const Wrapper = getWrapper(workspace);
expect(blockSuiteWorkspace.meta.docMetas.length).toBe(3); expect(docCollection.meta.docMetas.length).toBe(3);
const helperHook = renderHook( const helperHook = renderHook(() => useDocCollectionHelper(docCollection), {
() => useBlockSuiteWorkspaceHelper(blockSuiteWorkspace), wrapper: Wrapper,
{ });
wrapper: Wrapper, const pageMetaHook = renderHook(() => useBlockSuiteDocMeta(docCollection), {
} wrapper: Wrapper,
); });
const pageMetaHook = renderHook(
() => useBlockSuiteDocMeta(blockSuiteWorkspace),
{
wrapper: Wrapper,
}
);
await new Promise(resolve => setTimeout(resolve)); await new Promise(resolve => setTimeout(resolve));
expect(pageMetaHook.result.current.length).toBe(3); expect(pageMetaHook.result.current.length).toBe(3);
expect(blockSuiteWorkspace.meta.docMetas.length).toBe(3); expect(docCollection.meta.docMetas.length).toBe(3);
const page = helperHook.result.current.createDoc('page4'); const page = helperHook.result.current.createDoc('page4');
expect(page.id).toBe('page4'); expect(page.id).toBe('page4');
expect(blockSuiteWorkspace.meta.docMetas.length).toBe(4); expect(docCollection.meta.docMetas.length).toBe(4);
pageMetaHook.rerender(); pageMetaHook.rerender();
expect(pageMetaHook.result.current.length).toBe(4); expect(pageMetaHook.result.current.length).toBe(4);
}); });

View File

@@ -13,16 +13,13 @@ import { describe, expect, test, vi } from 'vitest';
import { beforeEach } from 'vitest'; import { beforeEach } from 'vitest';
import { configureTestingEnvironment } from '../../testing'; import { configureTestingEnvironment } from '../../testing';
import { useBlockSuiteWorkspacePageTitle } from '../use-block-suite-workspace-page-title'; import { useDocCollectionPageTitle } from '../use-block-suite-workspace-page-title';
const store = createStore(); const store = createStore();
const Component = () => { const Component = () => {
const workspace = useService(Workspace); const workspace = useService(Workspace);
const title = useBlockSuiteWorkspacePageTitle( const title = useDocCollectionPageTitle(workspace.docCollection, 'page0');
workspace.blockSuiteWorkspace,
'page0'
);
return <div>title: {title}</div>; return <div>title: {title}</div>;
}; };
@@ -30,7 +27,7 @@ beforeEach(async () => {
vi.useFakeTimers({ toFake: ['requestIdleCallback'] }); vi.useFakeTimers({ toFake: ['requestIdleCallback'] });
}); });
describe('useBlockSuiteWorkspacePageTitle', () => { describe('useDocCollectionPageTitle', () => {
test('basic', async () => { test('basic', async () => {
const { workspace, page } = await configureTestingEnvironment(); const { workspace, page } = await configureTestingEnvironment();
const { findByText, rerender } = render( const { findByText, rerender } = render(
@@ -43,7 +40,7 @@ describe('useBlockSuiteWorkspacePageTitle', () => {
</ServiceProviderContext.Provider> </ServiceProviderContext.Provider>
); );
expect(await findByText('title: Untitled')).toBeDefined(); expect(await findByText('title: Untitled')).toBeDefined();
workspace.blockSuiteWorkspace.setDocMeta(page.id, { title: '1' }); workspace.docCollection.setDocMeta(page.id, { title: '1' });
rerender( rerender(
<ServiceProviderContext.Provider value={page.services}> <ServiceProviderContext.Provider value={page.services}>
<Provider store={store}> <Provider store={store}>

View File

@@ -17,7 +17,7 @@ import { usePublicPages } from './use-is-shared-page';
export const useAllPageListConfig = () => { export const useAllPageListConfig = () => {
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const { getPublicMode } = usePublicPages(currentWorkspace); const { getPublicMode } = usePublicPages(currentWorkspace);
const workspace = currentWorkspace.blockSuiteWorkspace; const workspace = currentWorkspace.docCollection;
const pageMetas = useBlockSuiteDocMeta(workspace); const pageMetas = useBlockSuiteDocMeta(workspace);
const { isPreferredEdgeless } = usePageHelper(workspace); const { isPreferredEdgeless } = usePageHelper(workspace);
const pageMap = useMemo( const pageMap = useMemo(
@@ -25,7 +25,7 @@ export const useAllPageListConfig = () => {
[pageMetas] [pageMetas]
); );
const { toggleFavorite } = useBlockSuiteMetaHelper( const { toggleFavorite } = useBlockSuiteMetaHelper(
currentWorkspace.blockSuiteWorkspace currentWorkspace.docCollection
); );
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const onToggleFavoritePage = useCallback( const onToggleFavoritePage = useCallback(
@@ -45,7 +45,7 @@ export const useAllPageListConfig = () => {
allPages: pageMetas, allPages: pageMetas,
isEdgeless: isPreferredEdgeless, isEdgeless: isPreferredEdgeless,
getPublicMode, getPublicMode,
workspace: currentWorkspace.blockSuiteWorkspace, docCollection: currentWorkspace.docCollection,
getPage: id => pageMap[id], getPage: id => pageMap[id],
favoriteRender: page => { favoriteRender: page => {
return ( return (
@@ -61,7 +61,7 @@ export const useAllPageListConfig = () => {
pageMetas, pageMetas,
isPreferredEdgeless, isPreferredEdgeless,
getPublicMode, getPublicMode,
currentWorkspace.blockSuiteWorkspace, currentWorkspace.docCollection,
pageMap, pageMap,
onToggleFavoritePage, onToggleFavoritePage,
]); ]);

View File

@@ -1,22 +1,20 @@
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks'; import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
import { useBlockSuiteWorkspaceHelper } from '@affine/core/hooks/use-block-suite-workspace-helper'; import { useDocCollectionHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
import { CollectionService } from '@affine/core/modules/collection'; import { CollectionService } from '@affine/core/modules/collection';
import { PageRecordList, useService } from '@toeverything/infra'; import { PageRecordList, useService } from '@toeverything/infra';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { applyUpdate, encodeStateAsUpdate } from 'yjs'; import { applyUpdate, encodeStateAsUpdate } from 'yjs';
import type { BlockSuiteWorkspace } from '../../shared'; import type { DocCollection } from '../../shared';
import { useNavigateHelper } from '../use-navigate-helper'; import { useNavigateHelper } from '../use-navigate-helper';
import { useReferenceLinkHelper } from './use-reference-link-helper'; import { useReferenceLinkHelper } from './use-reference-link-helper';
export function useBlockSuiteMetaHelper( export function useBlockSuiteMetaHelper(docCollection: DocCollection) {
blockSuiteWorkspace: BlockSuiteWorkspace
) {
const { setDocMeta, getDocMeta, setDocReadonly, setDocTitle } = const { setDocMeta, getDocMeta, setDocReadonly, setDocTitle } =
useDocMetaHelper(blockSuiteWorkspace); useDocMetaHelper(docCollection);
const { addReferenceLink } = useReferenceLinkHelper(blockSuiteWorkspace); const { addReferenceLink } = useReferenceLinkHelper(docCollection);
const { createDoc } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace); const { createDoc } = useDocCollectionHelper(docCollection);
const { openPage } = useNavigateHelper(); const { openPage } = useNavigateHelper();
const collectionService = useService(CollectionService); const collectionService = useService(CollectionService);
const pageRecordList = useService(PageRecordList); const pageRecordList = useService(PageRecordList);
@@ -82,9 +80,9 @@ export function useBlockSuiteMetaHelper(
const permanentlyDeletePage = useCallback( const permanentlyDeletePage = useCallback(
(pageId: string) => { (pageId: string) => {
blockSuiteWorkspace.removeDoc(pageId); docCollection.removeDoc(pageId);
}, },
[blockSuiteWorkspace] [docCollection]
); );
/** /**
@@ -116,7 +114,7 @@ export function useBlockSuiteMetaHelper(
const currentPageMode = pageRecordList.record(pageId).value?.mode.value; const currentPageMode = pageRecordList.record(pageId).value?.mode.value;
const currentPageMeta = getDocMeta(pageId); const currentPageMeta = getDocMeta(pageId);
const newPage = createDoc(); const newPage = createDoc();
const currentPage = blockSuiteWorkspace.getDoc(pageId); const currentPage = docCollection.getDoc(pageId);
newPage.load(); newPage.load();
if (!currentPageMeta || !currentPage) { if (!currentPageMeta || !currentPage) {
@@ -142,10 +140,10 @@ export function useBlockSuiteMetaHelper(
.record(newPage.id) .record(newPage.id)
.value?.setMode(currentPageMode || 'page'); .value?.setMode(currentPageMode || 'page');
setDocTitle(newPage.id, newPageTitle); setDocTitle(newPage.id, newPageTitle);
openPageAfterDuplication && openPage(blockSuiteWorkspace.id, newPage.id); openPageAfterDuplication && openPage(docCollection.id, newPage.id);
}, },
[ [
blockSuiteWorkspace, docCollection,
createDoc, createDoc,
getDocMeta, getDocMeta,
openPage, openPage,

View File

@@ -1,13 +1,11 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import type { BlockSuiteWorkspace } from '../../shared'; import type { DocCollection } from '../../shared';
export function useReferenceLinkHelper( export function useReferenceLinkHelper(docCollection: DocCollection) {
blockSuiteWorkspace: BlockSuiteWorkspace
) {
const addReferenceLink = useCallback( const addReferenceLink = useCallback(
(pageId: string, referenceId: string) => { (pageId: string, referenceId: string) => {
const page = blockSuiteWorkspace?.getDoc(pageId); const page = docCollection?.getDoc(pageId);
if (!page) { if (!page) {
return; return;
} }
@@ -26,7 +24,7 @@ export function useReferenceLinkHelper(
frame && page.addBlock('affine:paragraph', { text }, frame.id); frame && page.addBlock('affine:paragraph', { text }, frame.id);
}, },
[blockSuiteWorkspace] [docCollection]
); );
return { return {

View File

@@ -24,9 +24,9 @@ export function useRegisterBlocksuiteEditorCommands() {
const mode = useLiveData(page.mode); const mode = useLiveData(page.mode);
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const blockSuiteWorkspace = workspace.blockSuiteWorkspace; const docCollection = workspace.docCollection;
const { getDocMeta } = useDocMetaHelper(blockSuiteWorkspace); const { getDocMeta } = useDocMetaHelper(docCollection);
const currentPage = blockSuiteWorkspace.getDoc(pageId); const currentPage = docCollection.getDoc(pageId);
assertExists(currentPage); assertExists(currentPage);
const pageMeta = getDocMeta(pageId); const pageMeta = getDocMeta(pageId);
assertExists(pageMeta); assertExists(pageMeta);
@@ -43,9 +43,9 @@ export function useRegisterBlocksuiteEditorCommands() {
}, [pageId, setPageHistoryModalState]); }, [pageId, setPageHistoryModalState]);
const { toggleFavorite, restoreFromTrash, duplicate } = const { toggleFavorite, restoreFromTrash, duplicate } =
useBlockSuiteMetaHelper(blockSuiteWorkspace); useBlockSuiteMetaHelper(docCollection);
const exportHandler = useExportPage(currentPage); const exportHandler = useExportPage(currentPage);
const { setTrashModal } = useTrashModalHelper(blockSuiteWorkspace); const { setTrashModal } = useTrashModalHelper(docCollection);
const onClickDelete = useCallback(() => { const onClickDelete = useCallback(() => {
setTrashModal({ setTrashModal({
open: true, open: true,

View File

@@ -70,7 +70,7 @@ export function getDragItemId(
export const useSidebarDrag = () => { export const useSidebarDrag = () => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const workspace = currentWorkspace.blockSuiteWorkspace; const workspace = currentWorkspace.docCollection;
const { setTrashModal } = useTrashModalHelper(workspace); const { setTrashModal } = useTrashModalHelper(workspace);
const { addToFavorite, removeFromFavorite } = const { addToFavorite, removeFromFavorite } =
useBlockSuiteMetaHelper(workspace); useBlockSuiteMetaHelper(workspace);

View File

@@ -1,17 +1,17 @@
import { toast } from '@affine/component'; import { toast } from '@affine/component';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { trashModalAtom } from '../../atoms/trash-modal'; import { trashModalAtom } from '../../atoms/trash-modal';
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper'; import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
export function useTrashModalHelper(blocksuiteWorkspace: Workspace) { export function useTrashModalHelper(docCollection: DocCollection) {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const [trashModal, setTrashModal] = useAtom(trashModalAtom); const [trashModal, setTrashModal] = useAtom(trashModalAtom);
const { pageIds } = trashModal; const { pageIds } = trashModal;
const { removeToTrash } = useBlockSuiteMetaHelper(blocksuiteWorkspace); const { removeToTrash } = useBlockSuiteMetaHelper(docCollection);
const handleOnConfirm = useCallback(() => { const handleOnConfirm = useCallback(() => {
pageIds.forEach(pageId => { pageIds.forEach(pageId => {

View File

@@ -20,8 +20,7 @@ const useReactiveAdapter = (adapter: WorkspacePropertiesAdapter) => {
} }
const disposables: (() => void)[] = []; const disposables: (() => void)[] = [];
disposables.push( disposables.push(
adapter.workspace.blockSuiteWorkspace.meta.docMetaUpdated.on(observe) adapter.workspace.docCollection.meta.docMetaUpdated.on(observe).dispose
.dispose
); );
adapter.properties.observeDeep(observe); adapter.properties.observeDeep(observe);
disposables.push(() => adapter.properties.unobserveDeep(observe)); disposables.push(() => adapter.properties.unobserveDeep(observe));

View File

@@ -1,25 +1,25 @@
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import type { Atom } from 'jotai'; import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai'; import { atom, useAtomValue } from 'jotai';
const weakMap = new WeakMap<Workspace, Atom<DocMeta[]>>(); const weakMap = new WeakMap<DocCollection, Atom<DocMeta[]>>();
// this hook is extracted from './use-block-suite-page-meta.ts' to avoid circular dependency // this hook is extracted from './use-block-suite-page-meta.ts' to avoid circular dependency
export function useAllBlockSuiteDocMeta( export function useAllBlockSuiteDocMeta(
blockSuiteWorkspace: Workspace docCollection: DocCollection
): DocMeta[] { ): DocMeta[] {
if (!weakMap.has(blockSuiteWorkspace)) { if (!weakMap.has(docCollection)) {
const baseAtom = atom<DocMeta[]>(blockSuiteWorkspace.meta.docMetas); const baseAtom = atom<DocMeta[]>(docCollection.meta.docMetas);
weakMap.set(blockSuiteWorkspace, baseAtom); weakMap.set(docCollection, baseAtom);
baseAtom.onMount = set => { baseAtom.onMount = set => {
set(blockSuiteWorkspace.meta.docMetas); set(docCollection.meta.docMetas);
const dispose = blockSuiteWorkspace.meta.docMetaUpdated.on(() => { const dispose = docCollection.meta.docMetaUpdated.on(() => {
set(blockSuiteWorkspace.meta.docMetas); set(docCollection.meta.docMetas);
}); });
return () => { return () => {
dispose.dispose(); dispose.dispose();
}; };
}; };
} }
return useAtomValue(weakMap.get(blockSuiteWorkspace) as Atom<DocMeta[]>); return useAtomValue(weakMap.get(docCollection) as Atom<DocMeta[]>);
} }

View File

@@ -1,11 +1,11 @@
import type { Doc, Workspace } from '@blocksuite/store'; import type { Doc, DocCollection } from '@blocksuite/store';
import { type Atom, atom, useAtomValue } from 'jotai'; import { type Atom, atom, useAtomValue } from 'jotai';
import { useBlockSuiteWorkspacePage } from './use-block-suite-workspace-page'; import { useDocCollectionPage } from './use-block-suite-workspace-page';
const weakMap = new WeakMap<Doc, Atom<string[]>>(); const weakMap = new WeakMap<Doc, Atom<string[]>>();
function getPageBacklinks(page: Doc): string[] { function getPageBacklinks(page: Doc): string[] {
return page.workspace.indexer.backlink return page.collection.indexer.backlink
.getBacklink(page.id) .getBacklink(page.id)
.map(linkNode => linkNode.pageId) .map(linkNode => linkNode.pageId)
.filter(id => id !== page.id); .filter(id => id !== page.id);
@@ -23,7 +23,7 @@ const getPageBacklinksAtom = (page: Doc | null) => {
page.slots.ready.on(() => { page.slots.ready.on(() => {
set(getPageBacklinks(page)); set(getPageBacklinks(page));
}), }),
page.workspace.indexer.backlink.slots.indexUpdated.on(() => { page.collection.indexer.backlink.slots.indexUpdated.on(() => {
set(getPageBacklinks(page)); set(getPageBacklinks(page));
}), }),
]; ];
@@ -38,9 +38,9 @@ const getPageBacklinksAtom = (page: Doc | null) => {
}; };
export function useBlockSuitePageBacklinks( export function useBlockSuitePageBacklinks(
blockSuiteWorkspace: Workspace, docCollection: DocCollection,
pageId: string docId: string
): string[] { ): string[] {
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId); const doc = useDocCollectionPage(docCollection, docId);
return useAtomValue(getPageBacklinksAtom(page)); return useAtomValue(getPageBacklinksAtom(doc));
} }

View File

@@ -1,6 +1,6 @@
import type { RootBlockModel } from '@blocksuite/blocks'; import type { RootBlockModel } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { DocMeta, Workspace } from '@blocksuite/store'; import type { DocCollection, DocMeta } from '@blocksuite/store';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useAllBlockSuiteDocMeta } from './use-all-block-suite-page-meta'; import { useAllBlockSuiteDocMeta } from './use-all-block-suite-page-meta';
@@ -11,9 +11,9 @@ import { useJournalHelper } from './use-journal';
* If you want to get all pageMetas, use `useAllBlockSuitePageMeta` instead * If you want to get all pageMetas, use `useAllBlockSuitePageMeta` instead
* @returns * @returns
*/ */
export function useBlockSuiteDocMeta(blocksuiteWorkspace: Workspace) { export function useBlockSuiteDocMeta(docCollection: DocCollection) {
const pageMetas = useAllBlockSuiteDocMeta(blocksuiteWorkspace); const pageMetas = useAllBlockSuiteDocMeta(docCollection);
const { isPageJournal } = useJournalHelper(blocksuiteWorkspace); const { isPageJournal } = useJournalHelper(docCollection);
return useMemo( return useMemo(
() => () =>
pageMetas.filter( pageMetas.filter(
@@ -23,11 +23,11 @@ export function useBlockSuiteDocMeta(blocksuiteWorkspace: Workspace) {
); );
} }
export function useDocMetaHelper(blockSuiteWorkspace: Workspace) { export function useDocMetaHelper(docCollection: DocCollection) {
return useMemo( return useMemo(
() => ({ () => ({
setDocTitle: (docId: string, newTitle: string) => { setDocTitle: (docId: string, newTitle: string) => {
const page = blockSuiteWorkspace.getDoc(docId); const page = docCollection.getDoc(docId);
assertExists(page); assertExists(page);
const pageBlock = page const pageBlock = page
.getBlockByFlavour('affine:page') .getBlockByFlavour('affine:page')
@@ -37,20 +37,20 @@ export function useDocMetaHelper(blockSuiteWorkspace: Workspace) {
pageBlock.title.delete(0, pageBlock.title.length); pageBlock.title.delete(0, pageBlock.title.length);
pageBlock.title.insert(newTitle, 0); pageBlock.title.insert(newTitle, 0);
}); });
blockSuiteWorkspace.meta.setDocMeta(docId, { title: newTitle }); docCollection.meta.setDocMeta(docId, { title: newTitle });
}, },
setDocReadonly: (docId: string, readonly: boolean) => { setDocReadonly: (docId: string, readonly: boolean) => {
const page = blockSuiteWorkspace.getDoc(docId); const page = docCollection.getDoc(docId);
assertExists(page); assertExists(page);
page.awarenessStore.setReadonly(page, readonly); page.awarenessStore.setReadonly(page, readonly);
}, },
setDocMeta: (docId: string, docMeta: Partial<DocMeta>) => { setDocMeta: (docId: string, docMeta: Partial<DocMeta>) => {
blockSuiteWorkspace.meta.setDocMeta(docId, docMeta); docCollection.meta.setDocMeta(docId, docMeta);
}, },
getDocMeta: (docId: string) => { getDocMeta: (docId: string) => {
return blockSuiteWorkspace.meta.getDocMeta(docId); return docCollection.meta.getDocMeta(docId);
}, },
}), }),
[blockSuiteWorkspace] [docCollection]
); );
} }

View File

@@ -1,12 +1,12 @@
import type { Doc, Workspace } from '@blocksuite/store'; import type { Doc, DocCollection } from '@blocksuite/store';
import { type Atom, atom, useAtomValue } from 'jotai'; import { type Atom, atom, useAtomValue } from 'jotai';
import { useBlockSuiteWorkspacePage } from './use-block-suite-workspace-page'; import { useDocCollectionPage } from './use-block-suite-workspace-page';
const weakMap = new WeakMap<Doc, Atom<string[]>>(); const weakMap = new WeakMap<Doc, Atom<string[]>>();
function getPageReferences(page: Doc): string[] { function getPageReferences(page: Doc): string[] {
return Object.values( return Object.values(
page.workspace.indexer.backlink.linkIndexMap[page.id] ?? {} page.collection.indexer.backlink.linkIndexMap[page.id] ?? {}
).flatMap(linkNodes => linkNodes.map(linkNode => linkNode.pageId)); ).flatMap(linkNodes => linkNodes.map(linkNode => linkNode.pageId));
} }
@@ -22,7 +22,7 @@ const getPageReferencesAtom = (page: Doc | null) => {
page.slots.ready.on(() => { page.slots.ready.on(() => {
set(getPageReferences(page)); set(getPageReferences(page));
}), }),
page.workspace.indexer.backlink.slots.indexUpdated.on(() => { page.collection.indexer.backlink.slots.indexUpdated.on(() => {
set(getPageReferences(page)); set(getPageReferences(page));
}), }),
]; ];
@@ -37,9 +37,9 @@ const getPageReferencesAtom = (page: Doc | null) => {
}; };
export function useBlockSuitePageReferences( export function useBlockSuitePageReferences(
blockSuiteWorkspace: Workspace, docCollection: DocCollection,
pageId: string pageId: string
): string[] { ): string[] {
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId); const page = useDocCollectionPage(docCollection, pageId);
return useAtomValue(getPageReferencesAtom(page)); return useAtomValue(getPageReferencesAtom(page));
} }

View File

@@ -1,13 +1,13 @@
import type { Doc, Workspace } from '@blocksuite/store'; import type { Doc, DocCollection } from '@blocksuite/store';
import { useMemo } from 'react'; import { useMemo } from 'react';
export function useBlockSuiteWorkspaceHelper(blockSuiteWorkspace: Workspace) { export function useDocCollectionHelper(docCollection: DocCollection) {
return useMemo( return useMemo(
() => ({ () => ({
createDoc: (pageId?: string): Doc => { createDoc: (pageId?: string): Doc => {
return blockSuiteWorkspace.createDoc({ id: pageId }); return docCollection.createDoc({ id: pageId });
}, },
}), }),
[blockSuiteWorkspace] [docCollection]
); );
} }

View File

@@ -1,14 +1,14 @@
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { Atom } from 'jotai'; import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai'; import { atom, useAtomValue } from 'jotai';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useJournalHelper, useJournalInfoHelper } from './use-journal'; import { useJournalHelper, useJournalInfoHelper } from './use-journal';
const weakMap = new WeakMap<Workspace, Map<string, Atom<string>>>(); const weakMap = new WeakMap<DocCollection, Map<string, Atom<string>>>();
function getAtom(w: Workspace, pageId: string): Atom<string> { function getAtom(w: DocCollection, pageId: string): Atom<string> {
if (!weakMap.has(w)) { if (!weakMap.has(w)) {
weakMap.set(w, new Map()); weakMap.set(w, new Map());
} }
@@ -32,33 +32,27 @@ function getAtom(w: Workspace, pageId: string): Atom<string> {
} }
} }
export function useBlockSuiteWorkspacePageTitle( export function useDocCollectionPageTitle(
blockSuiteWorkspace: Workspace, docCollection: DocCollection,
pageId: string pageId: string
) { ) {
const titleAtom = getAtom(blockSuiteWorkspace, pageId); const titleAtom = getAtom(docCollection, pageId);
assertExists(titleAtom); assertExists(titleAtom);
const title = useAtomValue(titleAtom); const title = useAtomValue(titleAtom);
const { localizedJournalDate } = useJournalInfoHelper( const { localizedJournalDate } = useJournalInfoHelper(docCollection, pageId);
blockSuiteWorkspace,
pageId
);
return localizedJournalDate || title; return localizedJournalDate || title;
} }
// This hook is NOT reactive to the page title change // This hook is NOT reactive to the page title change
export function useGetBlockSuiteWorkspacePageTitle( export function useGetDocCollectionPageTitle(docCollection: DocCollection) {
blockSuiteWorkspace: Workspace const { getLocalizedJournalDateString } = useJournalHelper(docCollection);
) {
const { getLocalizedJournalDateString } =
useJournalHelper(blockSuiteWorkspace);
return useCallback( return useCallback(
(pageId: string) => { (pageId: string) => {
return ( return (
getLocalizedJournalDateString(pageId) || getLocalizedJournalDateString(pageId) ||
blockSuiteWorkspace.getDoc(pageId)?.meta?.title docCollection.getDoc(pageId)?.meta?.title
); );
}, },
[blockSuiteWorkspace, getLocalizedJournalDateString] [docCollection, getLocalizedJournalDateString]
); );
} }

View File

@@ -1,26 +1,26 @@
import { DisposableGroup } from '@blocksuite/global/utils'; import { DisposableGroup } from '@blocksuite/global/utils';
import type { Doc, Workspace } from '@blocksuite/store'; import type { Doc, DocCollection } from '@blocksuite/store';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
export function useBlockSuiteWorkspacePage( export function useDocCollectionPage(
blockSuiteWorkspace: Workspace, docCollection: DocCollection,
pageId: string | null pageId: string | null
): Doc | null { ): Doc | null {
const [page, setPage] = useState( const [page, setPage] = useState(
pageId ? blockSuiteWorkspace.getDoc(pageId) : null pageId ? docCollection.getDoc(pageId) : null
); );
useEffect(() => { useEffect(() => {
const group = new DisposableGroup(); const group = new DisposableGroup();
group.add( group.add(
blockSuiteWorkspace.slots.docAdded.on(id => { docCollection.slots.docAdded.on(id => {
if (pageId === id) { if (pageId === id) {
setPage(blockSuiteWorkspace.getDoc(id)); setPage(docCollection.getDoc(id));
} }
}) })
); );
group.add( group.add(
blockSuiteWorkspace.slots.docRemoved.on(id => { docCollection.slots.docRemoved.on(id => {
if (pageId === id) { if (pageId === id) {
setPage(null); setPage(null);
} }
@@ -29,7 +29,7 @@ export function useBlockSuiteWorkspacePage(
return () => { return () => {
group.dispose(); group.dispose();
}; };
}, [blockSuiteWorkspace, pageId]); }, [docCollection, pageId]);
useEffect(() => { useEffect(() => {
if (page && !page.loaded) { if (page && !page.loaded) {

View File

@@ -2,10 +2,10 @@ import { initEmptyPage } from '@toeverything/infra';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import type { BlockSuiteWorkspace } from '../shared'; import type { DocCollection } from '../shared';
import { timestampToLocalDate } from '../utils'; import { timestampToLocalDate } from '../utils';
import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter'; import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter';
import { useBlockSuiteWorkspaceHelper } from './use-block-suite-workspace-helper'; import { useDocCollectionHelper } from './use-block-suite-workspace-helper';
import { useNavigateHelper } from './use-navigate-helper'; import { useNavigateHelper } from './use-navigate-helper';
type MaybeDate = Date | string | number; type MaybeDate = Date | string | number;
@@ -22,8 +22,8 @@ function toDayjs(j?: string | false) {
return day; return day;
} }
export const useJournalHelper = (workspace: BlockSuiteWorkspace) => { export const useJournalHelper = (docCollection: DocCollection) => {
const bsWorkspaceHelper = useBlockSuiteWorkspaceHelper(workspace); const bsWorkspaceHelper = useDocCollectionHelper(docCollection);
const adapter = useCurrentWorkspacePropertiesAdapter(); const adapter = useCurrentWorkspacePropertiesAdapter();
/** /**
@@ -35,7 +35,7 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
const title = day.format(JOURNAL_DATE_FORMAT); const title = day.format(JOURNAL_DATE_FORMAT);
const page = bsWorkspaceHelper.createDoc(); const page = bsWorkspaceHelper.createDoc();
// set created date to match the journal date // set created date to match the journal date
page.workspace.setDocMeta(page.id, { page.collection.setDocMeta(page.id, {
createDate: dayjs() createDate: dayjs()
.set('year', day.year()) .set('year', day.year())
.set('month', day.month()) .set('month', day.month())
@@ -63,7 +63,7 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
const getJournalsByDate = useCallback( const getJournalsByDate = useCallback(
(maybeDate: MaybeDate) => { (maybeDate: MaybeDate) => {
const day = dayjs(maybeDate); const day = dayjs(maybeDate);
return Array.from(workspace.docs.values()).filter(page => { return Array.from(docCollection.docs.values()).filter(page => {
const pageId = page.id; const pageId = page.id;
if (!isPageJournal(pageId)) return false; if (!isPageJournal(pageId)) return false;
if (page.meta?.trash) return false; if (page.meta?.trash) return false;
@@ -72,7 +72,7 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
return day.isSame(journalDate, 'day'); return day.isSame(journalDate, 'day');
}); });
}, },
[adapter, isPageJournal, workspace.docs] [adapter, isPageJournal, docCollection.docs]
); );
/** /**
@@ -150,18 +150,18 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
}; };
// split useJournalRouteHelper since it requires a <Route /> context, which may not work in lit // split useJournalRouteHelper since it requires a <Route /> context, which may not work in lit
export const useJournalRouteHelper = (workspace: BlockSuiteWorkspace) => { export const useJournalRouteHelper = (docCollection: DocCollection) => {
const navigateHelper = useNavigateHelper(); const navigateHelper = useNavigateHelper();
const { getJournalByDate } = useJournalHelper(workspace); const { getJournalByDate } = useJournalHelper(docCollection);
/** /**
* open journal by date, create one if not exist * open journal by date, create one if not exist
*/ */
const openJournal = useCallback( const openJournal = useCallback(
(maybeDate: MaybeDate) => { (maybeDate: MaybeDate) => {
const page = getJournalByDate(maybeDate); const page = getJournalByDate(maybeDate);
navigateHelper.openPage(workspace.id, page.id); navigateHelper.openPage(docCollection.id, page.id);
}, },
[getJournalByDate, navigateHelper, workspace.id] [getJournalByDate, navigateHelper, docCollection.id]
); );
/** /**
@@ -182,7 +182,7 @@ export const useJournalRouteHelper = (workspace: BlockSuiteWorkspace) => {
}; };
export const useJournalInfoHelper = ( export const useJournalInfoHelper = (
workspace: BlockSuiteWorkspace, docCollection: DocCollection,
pageId?: string | null pageId?: string | null
) => { ) => {
const { const {
@@ -190,7 +190,7 @@ export const useJournalInfoHelper = (
getJournalDateString, getJournalDateString,
getLocalizedJournalDateString, getLocalizedJournalDateString,
isPageTodayJournal, isPageTodayJournal,
} = useJournalHelper(workspace); } = useJournalHelper(docCollection);
return useMemo( return useMemo(
() => ({ () => ({

View File

@@ -24,7 +24,7 @@ export function useRegisterWorkspaceCommands() {
const theme = useTheme(); const theme = useTheme();
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const languageHelper = useLanguageHelper(); const languageHelper = useLanguageHelper();
const pageHelper = usePageHelper(currentWorkspace.blockSuiteWorkspace); const pageHelper = usePageHelper(currentWorkspace.docCollection);
const navigationHelper = useNavigateHelper(); const navigationHelper = useNavigateHelper();
const [editor] = useActiveBlocksuiteEditor(); const [editor] = useActiveBlocksuiteEditor();
@@ -45,14 +45,14 @@ export function useRegisterWorkspaceCommands() {
const unsub = registerAffineNavigationCommands({ const unsub = registerAffineNavigationCommands({
store, store,
t, t,
workspace: currentWorkspace.blockSuiteWorkspace, docCollection: currentWorkspace.docCollection,
navigationHelper, navigationHelper,
}); });
return () => { return () => {
unsub(); unsub();
}; };
}, [store, t, currentWorkspace.blockSuiteWorkspace, navigationHelper]); }, [store, t, currentWorkspace.docCollection, navigationHelper]);
// register AffineSettingsCommands // register AffineSettingsCommands
useEffect(() => { useEffect(() => {

View File

@@ -94,7 +94,7 @@ export const WorkspaceLayout = function WorkspaceLayout({
export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => { export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
const currentWorkspace = useService(Workspace); const currentWorkspace = useService(Workspace);
const { openPage } = useNavigateHelper(); const { openPage } = useNavigateHelper();
const pageHelper = usePageHelper(currentWorkspace.blockSuiteWorkspace); const pageHelper = usePageHelper(currentWorkspace.docCollection);
useRegisterWorkspaceCommands(); useRegisterWorkspaceCommands();
@@ -104,7 +104,7 @@ export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
// 0.8.0 ~ 0.8.1 // 0.8.0 ~ 0.8.1
// 0.8.0-beta.0 ~ 0.8.0-beta.3 // 0.8.0-beta.0 ~ 0.8.0-beta.3
// 0.8.0-canary.17 ~ 0.9.0-canary.3 // 0.8.0-canary.17 ~ 0.9.0-canary.3
const meta = currentWorkspace.blockSuiteWorkspace.doc.getMap('meta'); const meta = currentWorkspace.docCollection.doc.getMap('meta');
const blockVersions = meta.get('blockVersions'); const blockVersions = meta.get('blockVersions');
if ( if (
!(blockVersions instanceof YMap) && !(blockVersions instanceof YMap) &&
@@ -117,7 +117,7 @@ export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
new YMap(Object.entries(blockVersions as Record<string, number>)) new YMap(Object.entries(blockVersions as Record<string, number>))
); );
} }
}, [currentWorkspace.blockSuiteWorkspace.doc]); }, [currentWorkspace.docCollection.doc]);
const handleCreatePage = useCallback(() => { const handleCreatePage = useCallback(() => {
return pageHelper.createPage(); return pageHelper.createPage();

View File

@@ -17,11 +17,11 @@ export class CollectionService {
constructor(private readonly workspace: Workspace) {} constructor(private readonly workspace: Workspace) {}
private get doc() { private get doc() {
return this.workspace.blockSuiteWorkspace.doc; return this.workspace.docCollection.doc;
} }
private get setting() { private get setting() {
return this.workspace.blockSuiteWorkspace.doc.getMap(SETTING_KEY); return this.workspace.docCollection.doc.getMap(SETTING_KEY);
} }
private get collectionsYArray(): YArray<Collection> | undefined { private get collectionsYArray(): YArray<Collection> | undefined {
@@ -96,7 +96,7 @@ export class CollectionService {
return; return;
} }
const set = new Set(ids); const set = new Set(ids);
this.workspace.blockSuiteWorkspace.doc.transact(() => { this.workspace.docCollection.doc.transact(() => {
const indexList: number[] = []; const indexList: number[] = [];
const list: Collection[] = []; const list: Collection[] = [];
collectionsYArray.forEach((collection, i) => { collectionsYArray.forEach((collection, i) => {

View File

@@ -61,7 +61,7 @@ const PageItem = ({
const mode = useLiveData(pageRecord.mode); const mode = useLiveData(pageRecord.mode);
const workspace = useService(Workspace); const workspace = useService(Workspace);
const { isJournal } = useJournalInfoHelper( const { isJournal } = useJournalInfoHelper(
workspace.blockSuiteWorkspace, workspace.docCollection,
pageRecord.id pageRecord.id
); );
@@ -100,10 +100,10 @@ const EditorJournalPanel = () => {
const doc = useService(Doc); const doc = useService(Doc);
const workspace = useService(Workspace); const workspace = useService(Workspace);
const { journalDate, isJournal } = useJournalInfoHelper( const { journalDate, isJournal } = useJournalInfoHelper(
workspace.blockSuiteWorkspace, workspace.docCollection,
doc.id doc.id
); );
const { openJournal } = useJournalRouteHelper(workspace.blockSuiteWorkspace); const { openJournal } = useJournalRouteHelper(workspace.docCollection);
const [date, setDate] = useState(dayjs().format('YYYY-MM-DD')); const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
useEffect(() => { useEffect(() => {
@@ -314,7 +314,7 @@ const ConflictList = ({
const navigateHelper = useNavigateHelper(); const navigateHelper = useNavigateHelper();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const currentDoc = useService(Doc); const currentDoc = useService(Doc);
const { setTrashModal } = useTrashModalHelper(workspace.blockSuiteWorkspace); const { setTrashModal } = useTrashModalHelper(workspace.docCollection);
const handleOpenTrashModal = useCallback( const handleOpenTrashModal = useCallback(
(pageRecord: PageRecord) => { (pageRecord: PageRecord) => {
@@ -361,7 +361,7 @@ const JournalConflictBlock = ({ date }: JournalBlockProps) => {
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
const workspace = useService(Workspace); const workspace = useService(Workspace);
const pageRecordList = useService(PageRecordList); const pageRecordList = useService(PageRecordList);
const journalHelper = useJournalHelper(workspace.blockSuiteWorkspace); const journalHelper = useJournalHelper(workspace.docCollection);
const docs = journalHelper.getJournalsByDate(date.format('YYYY-MM-DD')); const docs = journalHelper.getJournalsByDate(date.format('YYYY-MM-DD'));
const pageRecords = useLiveData(pageRecordList.records).filter(v => { const pageRecords = useLiveData(pageRecordList.records).filter(v => {
return docs.some(doc => doc.id === v.id); return docs.some(doc => doc.id === v.id);

View File

@@ -28,10 +28,7 @@ export const MultiTabSidebarHeaderSwitcher = ({
FeatureType.Copilot FeatureType.Copilot
); );
const { isJournal } = useJournalInfoHelper( const { isJournal } = useJournalInfoHelper(workspace.docCollection, doc.id);
workspace.blockSuiteWorkspace,
doc.id
);
const exts = useMemo( const exts = useMemo(
() => () =>

View File

@@ -30,7 +30,7 @@ export class WorkspacePropertiesAdapter {
constructor(public readonly workspace: Workspace) { constructor(public readonly workspace: Workspace) {
// check if properties exists, if not, create one // check if properties exists, if not, create one
const rootDoc = workspace.blockSuiteWorkspace.doc; const rootDoc = workspace.docCollection.doc;
this.properties = rootDoc.getMap(AFFINE_PROPERTIES_ID); this.properties = rootDoc.getMap(AFFINE_PROPERTIES_ID);
this.proxy = createYProxy(this.properties); this.proxy = createYProxy(this.properties);
@@ -58,8 +58,8 @@ export class WorkspacePropertiesAdapter {
source: 'system', source: 'system',
type: PagePropertyType.Tags, type: PagePropertyType.Tags,
options: options:
this.workspace.blockSuiteWorkspace.meta.properties.tags this.workspace.docCollection.meta.properties.tags?.options ??
?.options ?? [], // better use a one time migration [], // better use a one time migration
}, },
}, },
}, },
@@ -89,8 +89,8 @@ export class WorkspacePropertiesAdapter {
} }
// leak some yjs abstraction to modify multiple properties at once // leak some yjs abstraction to modify multiple properties at once
transact = this.workspace.blockSuiteWorkspace.doc.transact.bind( transact = this.workspace.docCollection.doc.transact.bind(
this.workspace.blockSuiteWorkspace.doc this.workspace.docCollection.doc
); );
get schema() { get schema() {

View File

@@ -14,19 +14,18 @@ export class WorkspaceLegacyProperties {
} }
get properties() { get properties() {
return this.workspace.blockSuiteWorkspace.meta.properties; return this.workspace.docCollection.meta.properties;
} }
get tagOptions() { get tagOptions() {
return this.properties.tags?.options ?? []; return this.properties.tags?.options ?? [];
} }
updateProperties = (properties: DocsPropertiesMeta) => { updateProperties = (properties: DocsPropertiesMeta) => {
this.workspace.blockSuiteWorkspace.meta.setProperties(properties); this.workspace.docCollection.meta.setProperties(properties);
}; };
subscribe(cb: () => void) { subscribe(cb: () => void) {
const disposable = const disposable = this.workspace.docCollection.meta.docMetaUpdated.on(cb);
this.workspace.blockSuiteWorkspace.meta.docMetaUpdated.on(cb);
return disposable.dispose; return disposable.dispose;
} }
@@ -58,10 +57,10 @@ export class WorkspaceLegacyProperties {
}; };
removeTagOption = (id: string) => { removeTagOption = (id: string) => {
this.workspace.blockSuiteWorkspace.doc.transact(() => { this.workspace.docCollection.doc.transact(() => {
this.updateTagOptions(this.tagOptions.filter(o => o.id !== id)); this.updateTagOptions(this.tagOptions.filter(o => o.id !== id));
// need to remove tag from all pages // need to remove tag from all pages
this.workspace.blockSuiteWorkspace.docs.forEach(doc => { this.workspace.docCollection.docs.forEach(doc => {
const tags = doc.meta?.tags ?? []; const tags = doc.meta?.tags ?? [];
if (tags.includes(id)) { if (tags.includes(id)) {
this.updatePageTags( this.updatePageTags(
@@ -74,7 +73,7 @@ export class WorkspaceLegacyProperties {
}; };
updatePageTags = (pageId: string, tags: string[]) => { updatePageTags = (pageId: string, tags: string[]) => {
this.workspace.blockSuiteWorkspace.setDocMeta(pageId, { this.workspace.docCollection.setDocMeta(pageId, {
tags, tags,
}); });
}; };

View File

@@ -162,7 +162,7 @@ export const Component = () => {
.then(() => { .then(() => {
const { page } = workspace.services.get(PageManager).open(pageId); const { page } = workspace.services.get(PageManager).open(pageId);
workspace.blockSuiteWorkspace.awarenessStore.setReadonly( workspace.docCollection.awarenessStore.setReadonly(
page.blockSuiteDoc, page.blockSuiteDoc,
true true
); );
@@ -200,14 +200,14 @@ export const Component = () => {
<ShareHeader <ShareHeader
pageId={page.id} pageId={page.id}
publishMode={publishMode} publishMode={publishMode}
blockSuiteWorkspace={page.blockSuiteDoc.workspace} docCollection={page.blockSuiteDoc.collection}
/> />
<Scrollable.Root> <Scrollable.Root>
<Scrollable.Viewport className={styles.editorContainer}> <Scrollable.Viewport className={styles.editorContainer}>
<PageDetailEditor <PageDetailEditor
isPublic isPublic
publishMode={publishMode} publishMode={publishMode}
workspace={page.blockSuiteDoc.workspace} docCollection={page.blockSuiteDoc.collection}
pageId={page.id} pageId={page.id}
onLoad={() => noop} onLoad={() => noop}
/> />

View File

@@ -1,6 +1,6 @@
import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch'; import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch';
import ShareHeaderRightItem from '@affine/core/components/cloud/share-header-right-item'; import ShareHeaderRightItem from '@affine/core/components/cloud/share-header-right-item';
import type { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
import type { PageMode } from '@toeverything/infra'; import type { PageMode } from '@toeverything/infra';
import { BlocksuiteHeaderTitle } from '../../components/blocksuite/block-suite-header/title/index'; import { BlocksuiteHeaderTitle } from '../../components/blocksuite/block-suite-header/title/index';
@@ -9,28 +9,28 @@ import * as styles from './share-header.css';
export function ShareHeader({ export function ShareHeader({
pageId, pageId,
publishMode, publishMode,
blockSuiteWorkspace, docCollection,
}: { }: {
pageId: string; pageId: string;
publishMode: PageMode; publishMode: PageMode;
blockSuiteWorkspace: BlockSuiteWorkspace; docCollection: DocCollection;
}) { }) {
return ( return (
<div className={styles.header}> <div className={styles.header}>
<EditorModeSwitch <EditorModeSwitch
isPublic isPublic
blockSuiteWorkspace={blockSuiteWorkspace} docCollection={docCollection}
pageId={pageId} pageId={pageId}
publicMode={publishMode} publicMode={publishMode}
/> />
<BlocksuiteHeaderTitle <BlocksuiteHeaderTitle
blockSuiteWorkspace={blockSuiteWorkspace} docCollection={docCollection}
pageId={pageId} pageId={pageId}
isPublic={true} isPublic={true}
/> />
<div className={styles.spacer} /> <div className={styles.spacer} />
<ShareHeaderRightItem <ShareHeaderRightItem
workspaceId={blockSuiteWorkspace.id} workspaceId={docCollection.id}
pageId={pageId} pageId={pageId}
publishMode={publishMode} publishMode={publishMode}
/> />

Some files were not shown because too many files have changed in this diff Show More