snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped
This commit is contained in:
24
blocksuite/playground/apps/starter/data/affine-snapshot.ts
Normal file
24
blocksuite/playground/apps/starter/data/affine-snapshot.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { AffineSchemas } from '@blocksuite/affine/schemas';
|
||||
import { Schema, Text, type Workspace } from '@blocksuite/affine/store';
|
||||
import { ZipTransformer } from '@blocksuite/affine/widgets/linked-doc';
|
||||
export async function affineSnapshot(collection: Workspace, id: string) {
|
||||
const doc = collection.createDoc(id);
|
||||
doc.load();
|
||||
const store = doc.getStore();
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text('Affine Snapshot Test'),
|
||||
});
|
||||
store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
const path = '/apps/starter/data/snapshots/affine-default.zip';
|
||||
const response = await fetch(path);
|
||||
const file = await response.blob();
|
||||
const schema = new Schema();
|
||||
schema.register(AffineSchemas);
|
||||
await ZipTransformer.importDocs(collection, schema, file);
|
||||
}
|
||||
|
||||
affineSnapshot.id = 'affine-snapshot';
|
||||
affineSnapshot.displayName = 'Affine Snapshot Test';
|
||||
affineSnapshot.description = 'Affine Snapshot Test';
|
||||
136
blocksuite/playground/apps/starter/data/database.ts
Normal file
136
blocksuite/playground/apps/starter/data/database.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import {
|
||||
DatabaseBlockDataSource,
|
||||
databaseBlockProperties,
|
||||
} from '@blocksuite/affine/blocks/database';
|
||||
import {
|
||||
type DatabaseBlockModel,
|
||||
type ListType,
|
||||
type ParagraphType,
|
||||
} from '@blocksuite/affine/model';
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
import { groupTraitKey } from '@blocksuite/data-view';
|
||||
import { propertyPresets } from '@blocksuite/data-view/property-presets';
|
||||
import { viewPresets } from '@blocksuite/data-view/view-presets';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const database: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.createDoc(id);
|
||||
const store = doc.getStore();
|
||||
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text('BlockSuite Playground'),
|
||||
});
|
||||
store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = store.addBlock('affine:note', {}, rootId);
|
||||
const pId = store.addBlock('affine:paragraph', {}, noteId);
|
||||
const model = store.getModelById(pId);
|
||||
if (!model) {
|
||||
throw new Error('model is not found');
|
||||
}
|
||||
const addDatabase = (title: string, group = true) => {
|
||||
const databaseId = store.addBlock(
|
||||
'affine:database',
|
||||
{
|
||||
columns: [],
|
||||
cells: {},
|
||||
},
|
||||
noteId
|
||||
);
|
||||
const database = store.getModelById(databaseId) as DatabaseBlockModel;
|
||||
const datasource = new DatabaseBlockDataSource(database);
|
||||
datasource.viewManager.viewAdd('table');
|
||||
database.props.title = new Text(title);
|
||||
const richTextId = datasource.propertyAdd('end', {
|
||||
type: databaseBlockProperties.richTextColumnConfig.type,
|
||||
name: 'Rich Text',
|
||||
});
|
||||
Object.values([
|
||||
propertyPresets.multiSelectPropertyConfig,
|
||||
propertyPresets.datePropertyConfig,
|
||||
propertyPresets.numberPropertyConfig,
|
||||
databaseBlockProperties.linkColumnConfig,
|
||||
propertyPresets.checkboxPropertyConfig,
|
||||
propertyPresets.progressPropertyConfig,
|
||||
]).forEach(column => {
|
||||
datasource.propertyAdd('end', {
|
||||
type: column.type,
|
||||
name: column.config.name,
|
||||
});
|
||||
});
|
||||
if (group) {
|
||||
const groupTrait =
|
||||
datasource.viewManager.currentView$.value?.traitGet(groupTraitKey);
|
||||
groupTrait?.changeGroup(database.props.columns[1].id);
|
||||
}
|
||||
const paragraphTypes: ParagraphType[] = [
|
||||
'text',
|
||||
'quote',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
];
|
||||
paragraphTypes.forEach(type => {
|
||||
const id = store.addBlock(
|
||||
'affine:paragraph',
|
||||
{ type: type, text: new Text(`Paragraph type ${type}`) },
|
||||
databaseId
|
||||
);
|
||||
if (richTextId) {
|
||||
datasource.cellValueChange(
|
||||
id,
|
||||
richTextId,
|
||||
new Text(`Paragraph type ${type}`)
|
||||
);
|
||||
}
|
||||
});
|
||||
const listTypes: ListType[] = ['numbered', 'bulleted', 'todo', 'toggle'];
|
||||
|
||||
listTypes.forEach(type => {
|
||||
const id = store.addBlock(
|
||||
'affine:list',
|
||||
{ type: type, text: new Text(`List type ${type}`) },
|
||||
databaseId
|
||||
);
|
||||
if (richTextId) {
|
||||
datasource.cellValueChange(
|
||||
id,
|
||||
richTextId,
|
||||
new Text(`List type ${type}`)
|
||||
);
|
||||
}
|
||||
});
|
||||
// Add a paragraph after database
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
datasource.viewManager.viewAdd(viewPresets.kanbanViewMeta.type);
|
||||
|
||||
store.resetHistory();
|
||||
};
|
||||
// Add database block inside note block
|
||||
addDatabase('Database 1', false);
|
||||
addDatabase('Database 2');
|
||||
addDatabase('Database 3');
|
||||
addDatabase('Database 4');
|
||||
addDatabase('Database 5');
|
||||
addDatabase('Database 6');
|
||||
addDatabase('Database 7');
|
||||
addDatabase('Database 8');
|
||||
addDatabase('Database 9');
|
||||
addDatabase('Database 10');
|
||||
});
|
||||
};
|
||||
|
||||
database.id = 'database';
|
||||
database.displayName = 'Database Example';
|
||||
database.description = 'Database block basic example';
|
||||
55
blocksuite/playground/apps/starter/data/embed.ts
Normal file
55
blocksuite/playground/apps/starter/data/embed.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const embed: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.getDoc(id) ?? collection.createDoc(id);
|
||||
const store = doc.getStore();
|
||||
doc.clear();
|
||||
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
|
||||
const surfaceId = store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = store.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
|
||||
store.addBlock(
|
||||
'affine:embed-github',
|
||||
{
|
||||
url: 'https://github.com/toeverything/AFFiNE/pull/5453',
|
||||
},
|
||||
noteId
|
||||
);
|
||||
store.addBlock(
|
||||
'affine:embed-github',
|
||||
{
|
||||
url: 'https://www.github.com/toeverything/blocksuite/pull/5927',
|
||||
style: 'vertical',
|
||||
xywh: '[0, 400, 364, 390]',
|
||||
},
|
||||
surfaceId
|
||||
);
|
||||
store.addBlock(
|
||||
'affine:embed-github',
|
||||
{
|
||||
url: 'https://github.com/Milkdown/milkdown/pull/1215',
|
||||
xywh: '[500, 400, 752, 116]',
|
||||
},
|
||||
surfaceId
|
||||
);
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
store.resetHistory();
|
||||
};
|
||||
|
||||
embed.id = 'embed';
|
||||
embed.displayName = 'Example for embed blocks';
|
||||
embed.description = 'Example for embed blocks';
|
||||
29
blocksuite/playground/apps/starter/data/empty.ts
Normal file
29
blocksuite/playground/apps/starter/data/empty.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const empty: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.getDoc(id) ?? collection.createDoc(id);
|
||||
const store = doc.getStore();
|
||||
doc.clear();
|
||||
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
|
||||
store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = store.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
store.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
store.resetHistory();
|
||||
};
|
||||
|
||||
empty.id = 'empty';
|
||||
empty.displayName = 'Empty Editor';
|
||||
empty.description = 'Start from empty editor';
|
||||
99
blocksuite/playground/apps/starter/data/heavy-whiteboard.ts
Normal file
99
blocksuite/playground/apps/starter/data/heavy-whiteboard.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { SerializedXYWH } from '@blocksuite/affine/global/gfx';
|
||||
import {
|
||||
Boxed,
|
||||
nanoid,
|
||||
native2Y,
|
||||
Text,
|
||||
type Workspace,
|
||||
} from '@blocksuite/affine/store';
|
||||
import { DEFAULT_ROUGHNESS } from '@blocksuite/affine-model';
|
||||
import type * as Y from 'yjs';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
const SHAPE_TYPES = ['rect', 'triangle', 'ellipse', 'diamond'];
|
||||
const params = new URLSearchParams(location.search);
|
||||
|
||||
function createShapes(count: number): Record<string, unknown> {
|
||||
const surfaceBlocks: Record<string, unknown> = {};
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const x = Math.random() * count * 2;
|
||||
const y = Math.random() * count * 2;
|
||||
const id = nanoid();
|
||||
surfaceBlocks[id] = native2Y(
|
||||
{
|
||||
id,
|
||||
index: 'a0',
|
||||
type: 'shape',
|
||||
xywh: `[${x},${y},100,100]`,
|
||||
seed: Math.floor(Math.random() * 2 ** 31),
|
||||
shapeType: SHAPE_TYPES[Math.floor(Math.random() * 40) % 4],
|
||||
radius: 0,
|
||||
filled: false,
|
||||
fillColor: '--affine-palette-shape-yellow',
|
||||
strokeWidth: 4,
|
||||
strokeColor: '--affine-palette-line-yellow',
|
||||
strokeStyle: 'solid',
|
||||
roughness: DEFAULT_ROUGHNESS,
|
||||
},
|
||||
{ deep: false }
|
||||
);
|
||||
}
|
||||
return surfaceBlocks;
|
||||
}
|
||||
|
||||
const SHAPES_COUNT = 100;
|
||||
const RANGE = 2000;
|
||||
|
||||
export const heavyWhiteboard: InitFn = (collection: Workspace, id: string) => {
|
||||
const count = Number(params.get('count')) || SHAPES_COUNT;
|
||||
const enableShapes = !!params.get('shapes');
|
||||
|
||||
const doc = collection.createDoc(id);
|
||||
const store = doc.getStore();
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
|
||||
const surfaceBlocks = enableShapes ? createShapes(count) : {};
|
||||
|
||||
store.addBlock(
|
||||
'affine:surface',
|
||||
{
|
||||
elements: new Boxed(native2Y(surfaceBlocks, { deep: false })) as Boxed<
|
||||
Y.Map<Y.Map<unknown>>
|
||||
>,
|
||||
},
|
||||
rootId
|
||||
);
|
||||
|
||||
let i = 0;
|
||||
// Add note block inside root block
|
||||
for (i = 0; i < count; i++) {
|
||||
const x = Math.random() * RANGE - RANGE / 2;
|
||||
const y = Math.random() * RANGE - RANGE / 2;
|
||||
const noteId = store.addBlock(
|
||||
'affine:note',
|
||||
{
|
||||
xywh: `[${x}, ${y}, 100, 50]` as SerializedXYWH,
|
||||
},
|
||||
rootId
|
||||
);
|
||||
// Add paragraph block inside note block
|
||||
store.addBlock(
|
||||
'affine:paragraph',
|
||||
{
|
||||
text: new Text('Note #' + i),
|
||||
},
|
||||
noteId
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
heavyWhiteboard.id = 'heavy-whiteboard';
|
||||
heavyWhiteboard.displayName = 'Heavy Whiteboard';
|
||||
heavyWhiteboard.description = 'Heavy Whiteboard on 200 elements by default';
|
||||
36
blocksuite/playground/apps/starter/data/heavy.ts
Normal file
36
blocksuite/playground/apps/starter/data/heavy.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
|
||||
export const heavy: InitFn = (collection: Workspace, docId: string) => {
|
||||
const count = Number(params.get('count')) || 1000;
|
||||
|
||||
const doc = collection.createDoc(docId);
|
||||
const store = doc.getStore();
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = store.addBlock('affine:note', {}, rootId);
|
||||
for (let i = 0; i < count; i++) {
|
||||
// Add paragraph block inside note block
|
||||
store.addBlock(
|
||||
'affine:paragraph',
|
||||
{
|
||||
text: new Text('Hello, world! ' + i),
|
||||
},
|
||||
noteId
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
heavy.id = 'heavy';
|
||||
heavy.displayName = 'Heavy Example';
|
||||
heavy.description = 'Heavy example on thousands of paragraph blocks';
|
||||
19
blocksuite/playground/apps/starter/data/index.ts
Normal file
19
blocksuite/playground/apps/starter/data/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Manually create initial page structure.
|
||||
* In collaboration mode or on page refresh with local persistence,
|
||||
* the page structure will be automatically loaded from provider.
|
||||
* In these cases, these functions should not be called.
|
||||
*/
|
||||
export * from './affine-snapshot.js';
|
||||
export * from './database.js';
|
||||
export * from './embed.js';
|
||||
export * from './empty.js';
|
||||
export * from './heavy.js';
|
||||
export * from './heavy-whiteboard.js';
|
||||
export * from './linked.js';
|
||||
export * from './multiple-editor.js';
|
||||
export * from './pending-structs.js';
|
||||
export * from './preset.js';
|
||||
export * from './synced.js';
|
||||
export type { InitFn } from './utils.js';
|
||||
export * from './version-mismatch.js';
|
||||
82
blocksuite/playground/apps/starter/data/linked.ts
Normal file
82
blocksuite/playground/apps/starter/data/linked.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const linked: InitFn = (collection: Workspace, id: string) => {
|
||||
const docA =
|
||||
collection.getDoc(id)?.getStore({ id }) ??
|
||||
collection.createDoc(id).getStore({ id });
|
||||
|
||||
const docBId = 'doc:linked-page';
|
||||
const docB = collection.createDoc(docBId).getStore();
|
||||
|
||||
const docCId = 'doc:linked-edgeless';
|
||||
const docC = collection.createDoc(docCId).getStore();
|
||||
|
||||
docA.doc.clear();
|
||||
docB.doc.clear();
|
||||
docC.doc.clear();
|
||||
|
||||
docB.load(() => {
|
||||
const rootId = docB.addBlock('affine:page', {
|
||||
title: new Text(''),
|
||||
});
|
||||
|
||||
docB.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = docB.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
docB.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
docC.load(() => {
|
||||
const rootId = docC.addBlock('affine:page', {
|
||||
title: new Text(''),
|
||||
});
|
||||
|
||||
docC.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = docC.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
docC.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
docA.load();
|
||||
// Add root block and surface block at root level
|
||||
const rootId = docA.addBlock('affine:page', {
|
||||
title: new Text('Doc A'),
|
||||
});
|
||||
|
||||
docA.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = docA.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
docA.addBlock('affine:paragraph', {}, noteId);
|
||||
|
||||
docA.addBlock('affine:embed-linked-doc', { pageId: docBId }, noteId);
|
||||
|
||||
docA.addBlock(
|
||||
'affine:embed-linked-doc',
|
||||
{ pageId: 'doc:deleted-example' },
|
||||
noteId
|
||||
);
|
||||
|
||||
docA.addBlock('affine:embed-linked-doc', { pageId: docCId }, noteId);
|
||||
|
||||
docA.addBlock(
|
||||
'affine:embed-linked-doc',
|
||||
{ pageId: 'doc:deleted-example-edgeless' },
|
||||
noteId
|
||||
);
|
||||
|
||||
docA.resetHistory();
|
||||
docB.resetHistory();
|
||||
docC.resetHistory();
|
||||
};
|
||||
|
||||
linked.id = 'linked';
|
||||
linked.displayName = 'Linked Doc Editor';
|
||||
linked.description = 'A demo with linked docs';
|
||||
72
blocksuite/playground/apps/starter/data/multiple-editor.ts
Normal file
72
blocksuite/playground/apps/starter/data/multiple-editor.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
import { createTestEditor } from '../utils/extensions.js';
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const multiEditor: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.createDoc(id).getStore({ id });
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = doc.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
|
||||
doc.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = doc.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
doc.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
doc.resetHistory();
|
||||
|
||||
const app = document.getElementById('app');
|
||||
if (app) {
|
||||
const editor = createTestEditor(doc, collection);
|
||||
editor.style.borderRight = '1px solid var(--affine-border-color)';
|
||||
|
||||
app.append(editor);
|
||||
app.style.display = 'flex';
|
||||
}
|
||||
};
|
||||
|
||||
multiEditor.id = 'multiple-editor';
|
||||
multiEditor.displayName = 'Multiple Editor Example';
|
||||
multiEditor.description = 'Multiple Editor basic example';
|
||||
|
||||
export const multiEditorVertical: InitFn = (
|
||||
collection: Workspace,
|
||||
docId: string
|
||||
) => {
|
||||
const doc = collection.createDoc(docId).getStore();
|
||||
doc.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = doc.addBlock('affine:page', {
|
||||
title: new Text(),
|
||||
});
|
||||
|
||||
doc.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = doc.addBlock('affine:note', {}, rootId);
|
||||
// Add paragraph block inside note block
|
||||
doc.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
doc.resetHistory();
|
||||
|
||||
const app = document.getElementById('app');
|
||||
if (app) {
|
||||
const editor = createTestEditor(doc, collection);
|
||||
editor.style.borderBottom = '1px solid var(--affine-border-color)';
|
||||
|
||||
app.append(editor);
|
||||
app.style.display = 'flex';
|
||||
app.style.flexDirection = 'column';
|
||||
}
|
||||
};
|
||||
|
||||
multiEditorVertical.id = 'multiple-editor-vertical';
|
||||
multiEditorVertical.displayName = 'Vertical Multiple Editor Example';
|
||||
multiEditorVertical.description = 'Multiple Editor vertical layout example';
|
||||
39
blocksuite/playground/apps/starter/data/pending-structs.ts
Normal file
39
blocksuite/playground/apps/starter/data/pending-structs.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const pendingStructs: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.createDoc(id).getStore({ id });
|
||||
const tempDoc = collection.createDoc('tempDoc').getStore();
|
||||
doc.load();
|
||||
tempDoc.load(() => {
|
||||
const rootId = tempDoc.addBlock('affine:page', {
|
||||
title: new Text('Pending Structs'),
|
||||
});
|
||||
const vec = Y.encodeStateVector(tempDoc.spaceDoc);
|
||||
|
||||
// To avoid pending structs, uncomment the following line
|
||||
// const update = Y.encodeStateAsUpdate(tempDoc.spaceDoc);
|
||||
|
||||
tempDoc.addBlock('affine:surface', {}, rootId);
|
||||
// Add note block inside root block
|
||||
const noteId = tempDoc.addBlock('affine:note', {}, rootId);
|
||||
tempDoc.addBlock(
|
||||
'affine:paragraph',
|
||||
{
|
||||
text: new Text('This is a paragraph block'),
|
||||
},
|
||||
noteId
|
||||
);
|
||||
const diff = Y.encodeStateAsUpdate(tempDoc.spaceDoc, vec);
|
||||
// To avoid pending structs, uncomment the following line
|
||||
// Y.applyUpdate(doc.spaceDoc, update);
|
||||
|
||||
Y.applyUpdate(doc.spaceDoc, diff);
|
||||
});
|
||||
};
|
||||
|
||||
pendingStructs.id = 'pending-structs';
|
||||
pendingStructs.displayName = 'Pending Structs';
|
||||
pendingStructs.description = 'Doc with pending structs';
|
||||
48
blocksuite/playground/apps/starter/data/preset.ts
Normal file
48
blocksuite/playground/apps/starter/data/preset.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
import { MarkdownTransformer } from '@blocksuite/affine/widgets/linked-doc';
|
||||
import { getTestStoreManager } from '@blocksuite/integration-test/store';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
const presetMarkdown = `Click the 🔁 button to switch between editors dynamically - they are fully compatible!`;
|
||||
|
||||
export const preset: InitFn = async (collection: Workspace, id: string) => {
|
||||
let doc = collection.getDoc(id);
|
||||
const hasDoc = !!doc;
|
||||
if (!doc) {
|
||||
doc = collection.createDoc(id);
|
||||
}
|
||||
|
||||
const store = doc.getStore({ id });
|
||||
store.load();
|
||||
|
||||
// Run only once on all clients.
|
||||
let noteId: string;
|
||||
if (!hasDoc) {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = store.addBlock('affine:page', {
|
||||
title: new Text('BlockSuite Playground'),
|
||||
});
|
||||
store.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
noteId = store.addBlock(
|
||||
'affine:note',
|
||||
{ xywh: '[0, 100, 800, 640]' },
|
||||
rootId
|
||||
);
|
||||
// Import preset markdown content inside note block
|
||||
await MarkdownTransformer.importMarkdownToBlock({
|
||||
doc: store,
|
||||
blockId: noteId,
|
||||
markdown: presetMarkdown,
|
||||
extensions: getTestStoreManager().get('store'),
|
||||
});
|
||||
}
|
||||
|
||||
store.resetHistory();
|
||||
};
|
||||
|
||||
preset.id = 'preset';
|
||||
preset.displayName = 'BlockSuite Starter';
|
||||
preset.description = 'Start from friendly introduction';
|
||||
175
blocksuite/playground/apps/starter/data/synced.ts
Normal file
175
blocksuite/playground/apps/starter/data/synced.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { Text, type Workspace } from '@blocksuite/affine/store';
|
||||
import { MarkdownTransformer } from '@blocksuite/affine/widgets/linked-doc';
|
||||
import { getTestStoreManager } from '@blocksuite/integration-test/store';
|
||||
|
||||
import type { InitFn } from './utils';
|
||||
|
||||
const syncedDocMarkdown = `We share some of our findings from developing local-first software prototypes at [Ink & Switch](https://www.inkandswitch.com/) over the course of several years. These experiments test the viability of CRDTs in practice, and explore the user interface challenges for this new data model. Lastly, we suggest some next steps for moving towards local-first software: for researchers, for app developers, and a startup opportunity for entrepreneurs.
|
||||
|
||||
This article has also been published [in PDF format](https://www.inkandswitch.com/local-first/static/local-first.pdf) in the proceedings of the [Onward! 2019 conference](https://2019.splashcon.org/track/splash-2019-Onward-Essays). Please cite it as:
|
||||
|
||||
> Martin Kleppmann, Adam Wiggins, Peter van Hardenberg, and Mark McGranaghan. Local-first software: you own your data, in spite of the cloud. 2019 ACM SIGPLAN International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software (Onward!), October 2019, pages 154-178. [doi:10.1145/3359591.3359737](https://doi.org/10.1145/3359591.3359737)
|
||||
|
||||
We welcome your feedback: [@inkandswitch](https://twitter.com/inkandswitch) or hello@inkandswitch.com.`;
|
||||
|
||||
export const synced: InitFn = (collection: Workspace, id: string) => {
|
||||
const docMain =
|
||||
collection.getDoc(id)?.getStore({ id }) ??
|
||||
collection.createDoc(id).getStore({ id });
|
||||
|
||||
const docSyncedPageId = 'doc:synced-page';
|
||||
const docSyncedPage = collection.createDoc(docSyncedPageId).getStore();
|
||||
|
||||
const docSyncedEdgelessId = 'doc:synced-edgeless';
|
||||
const docSyncedEdgeless = collection
|
||||
.createDoc(docSyncedEdgelessId)
|
||||
.getStore();
|
||||
|
||||
docMain.doc.clear();
|
||||
docSyncedPage.doc.clear();
|
||||
docSyncedEdgeless.doc.clear();
|
||||
|
||||
docSyncedPage.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = docSyncedPage.addBlock('affine:page', {
|
||||
title: new Text('Synced - Page View'),
|
||||
});
|
||||
|
||||
docSyncedPage.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = docSyncedPage.addBlock('affine:note', {}, rootId);
|
||||
|
||||
// Add markdown to note block
|
||||
MarkdownTransformer.importMarkdownToBlock({
|
||||
doc: docSyncedPage,
|
||||
blockId: noteId,
|
||||
markdown: syncedDocMarkdown,
|
||||
extensions: getTestStoreManager().get('store'),
|
||||
}).catch(console.error);
|
||||
});
|
||||
|
||||
docSyncedEdgeless.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = docSyncedEdgeless.addBlock('affine:page', {
|
||||
title: new Text('Synced - Edgeless View'),
|
||||
});
|
||||
|
||||
docSyncedEdgeless.addBlock('affine:surface', {}, rootId);
|
||||
|
||||
// Add note block inside root block
|
||||
const noteId = docSyncedEdgeless.addBlock('affine:note', {}, rootId);
|
||||
|
||||
// Add markdown to note block
|
||||
MarkdownTransformer.importMarkdownToBlock({
|
||||
doc: docSyncedEdgeless,
|
||||
blockId: noteId,
|
||||
markdown: syncedDocMarkdown,
|
||||
extensions: getTestStoreManager().get('store'),
|
||||
}).catch(console.error);
|
||||
});
|
||||
|
||||
docMain.load(() => {
|
||||
// Add root block and surface block at root level
|
||||
const rootId = docMain.addBlock('affine:page', {
|
||||
title: new Text('Home doc, having synced blocks'),
|
||||
});
|
||||
|
||||
const surfaceId = docMain.addBlock('affine:surface', {}, rootId);
|
||||
const noteId = docMain.addBlock('affine:note', {}, rootId);
|
||||
|
||||
// Add markdown to note block
|
||||
MarkdownTransformer.importMarkdownToBlock({
|
||||
doc: docMain,
|
||||
blockId: noteId,
|
||||
markdown: syncedDocMarkdown,
|
||||
extensions: getTestStoreManager().get('store'),
|
||||
})
|
||||
.then(() => {
|
||||
// Add synced block - self
|
||||
docMain.addBlock(
|
||||
'affine:paragraph',
|
||||
{
|
||||
text: new Text('Cyclic / Matryoshka synced block 👇'),
|
||||
type: 'h4',
|
||||
},
|
||||
noteId
|
||||
);
|
||||
|
||||
// Add synced block - self
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: id,
|
||||
},
|
||||
noteId
|
||||
);
|
||||
|
||||
// Add synced block - page view
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: docSyncedPageId,
|
||||
},
|
||||
noteId
|
||||
);
|
||||
|
||||
// Add synced block - edgeless view
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: docSyncedEdgelessId,
|
||||
},
|
||||
noteId
|
||||
);
|
||||
|
||||
// Add synced block - page view
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: docSyncedPageId,
|
||||
xywh: '[-1000, 0, 752, 455]',
|
||||
},
|
||||
surfaceId
|
||||
);
|
||||
|
||||
// Add synced block - edgeless view
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: docSyncedEdgelessId,
|
||||
xywh: '[-1000, 500, 752, 455]',
|
||||
},
|
||||
surfaceId
|
||||
);
|
||||
|
||||
// Add synced block - self
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: id,
|
||||
xywh: '[-1000, 1000, 752, 455]',
|
||||
},
|
||||
surfaceId
|
||||
);
|
||||
|
||||
// Add synced block - self
|
||||
docMain.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
pageId: 'doc:deleted-page',
|
||||
},
|
||||
noteId
|
||||
);
|
||||
})
|
||||
.catch(console.error);
|
||||
});
|
||||
|
||||
docSyncedEdgeless.resetHistory();
|
||||
docSyncedPage.resetHistory();
|
||||
docMain.resetHistory();
|
||||
};
|
||||
|
||||
synced.id = 'synced';
|
||||
synced.displayName = 'Synced block demo';
|
||||
synced.description = 'A simple demo for synced block';
|
||||
8
blocksuite/playground/apps/starter/data/utils.ts
Normal file
8
blocksuite/playground/apps/starter/data/utils.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { Workspace } from '@blocksuite/affine/store';
|
||||
|
||||
export interface InitFn {
|
||||
(collection: Workspace, docId: string): Promise<void> | void;
|
||||
id: string;
|
||||
displayName: string;
|
||||
description: string;
|
||||
}
|
||||
36
blocksuite/playground/apps/starter/data/version-mismatch.ts
Normal file
36
blocksuite/playground/apps/starter/data/version-mismatch.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { Workspace } from '@blocksuite/affine/store';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { InitFn } from './utils.js';
|
||||
|
||||
export const versionMismatch: InitFn = (collection: Workspace, id: string) => {
|
||||
const doc = collection.createDoc(id).getStore({ id });
|
||||
const tempDoc = collection.createDoc('tempDoc').getStore();
|
||||
doc.load();
|
||||
|
||||
tempDoc.load(() => {
|
||||
const rootId = tempDoc.addBlock('affine:page', {});
|
||||
tempDoc.addBlock('affine:surface', {}, rootId);
|
||||
const noteId = tempDoc.addBlock(
|
||||
'affine:note',
|
||||
{ xywh: '[0, 100, 800, 640]' },
|
||||
rootId
|
||||
);
|
||||
const paragraphId = tempDoc.addBlock('affine:paragraph', {}, noteId);
|
||||
const blocks = tempDoc.spaceDoc.get('blocks') as Y.Map<unknown>;
|
||||
const paragraph = blocks.get(paragraphId) as Y.Map<unknown>;
|
||||
paragraph.set('sys:version', (paragraph.get('sys:version') as number) + 1);
|
||||
|
||||
const update = Y.encodeStateAsUpdate(tempDoc.spaceDoc);
|
||||
|
||||
Y.applyUpdate(doc.spaceDoc, update);
|
||||
doc.addBlock('affine:paragraph', {}, noteId);
|
||||
});
|
||||
|
||||
collection.removeDoc('tempDoc');
|
||||
doc.resetHistory();
|
||||
};
|
||||
|
||||
versionMismatch.id = 'version-mismatch';
|
||||
versionMismatch.displayName = 'Version Mismatch';
|
||||
versionMismatch.description = 'Error boundary when version mismatch in data';
|
||||
Reference in New Issue
Block a user