feat(editor): add feature flag service (#9592)

This commit is contained in:
Saul-Mirone
2025-01-08 15:46:31 +00:00
parent fd26b72255
commit 3683297ccf
55 changed files with 283 additions and 188 deletions
@@ -2,6 +2,7 @@ import type { DefaultOpenProperty } from '@affine/core/components/doc-properties
import {
type DocMode,
EdgelessRootService,
FeatureFlagService as BSFeatureFlagService,
HighlightSelection,
type ReferenceParams,
} from '@blocksuite/affine/blocks';
@@ -16,6 +17,7 @@ import { defaults, isEqual, omit } from 'lodash-es';
import { skip } from 'rxjs';
import type { DocService } from '../../doc';
import { AFFINE_FLAGS, type FeatureFlagService } from '../../feature-flag';
import { paramsParseOptions, preprocessParams } from '../../navigation/utils';
import type { WorkbenchView } from '../../workbench';
import type { WorkspaceService } from '../../workspace';
@@ -193,6 +195,8 @@ export class Editor extends Entity {
if (this.editorContainer$.value) {
throw new Error('already bound');
}
this._setupBlocksuiteEditorFlags(editorContainer);
this.editorContainer$.next(editorContainer);
const unsubs: (() => void)[] = [];
@@ -325,9 +329,24 @@ export class Editor extends Entity {
};
}
private _setupBlocksuiteEditorFlags(editorContainer: AffineEditorContainer) {
const affineFeatureFlagService = this.featureFlagService;
const bsFeatureFlagService = editorContainer.doc.get(BSFeatureFlagService);
Object.entries(AFFINE_FLAGS).forEach(([key, flag]) => {
if (flag.category === 'blocksuite') {
const value =
affineFeatureFlagService.flags[key as keyof AFFINE_FLAGS].value;
if (value !== undefined) {
bsFeatureFlagService.setFlag(flag.bsFlag, value);
}
}
});
}
constructor(
private readonly docService: DocService,
private readonly workspaceService: WorkspaceService
private readonly workspaceService: WorkspaceService,
private readonly featureFlagService: FeatureFlagService
) {
super();
}
@@ -1,6 +1,7 @@
import { type Framework } from '@toeverything/infra';
import { DocScope, DocService } from '../doc';
import { FeatureFlagService } from '../feature-flag';
import { WorkspaceScope, WorkspaceService } from '../workspace';
import { Editor } from './entities/editor';
import { EditorScope } from './scopes/editor';
@@ -18,7 +19,7 @@ export function configureEditorModule(framework: Framework) {
.scope(WorkspaceScope)
.scope(DocScope)
.service(EditorsService)
.entity(Editor, [DocService, WorkspaceService])
.entity(Editor, [DocService, WorkspaceService, FeatureFlagService])
.scope(EditorScope)
.service(EditorService, [EditorScope]);
}
@@ -2,27 +2,12 @@ import { OnEvent, Service } from '@toeverything/infra';
import { distinctUntilChanged, skip } from 'rxjs';
import { ApplicationStarted } from '../../lifecycle';
import type { Workspace } from '../../workspace';
import { WorkspaceInitialized } from '../../workspace/events';
import { AFFINE_FLAGS } from '../constant';
import { Flags, type FlagsExt } from '../entities/flags';
@OnEvent(WorkspaceInitialized, e => e.setupBlocksuiteEditorFlags)
@OnEvent(ApplicationStarted, e => e.setupRestartListener)
export class FeatureFlagService extends Service {
flags = this.framework.createEntity(Flags) as FlagsExt;
setupBlocksuiteEditorFlags(workspace: Workspace) {
for (const [key, flag] of Object.entries(AFFINE_FLAGS)) {
if (flag.category === 'blocksuite') {
const value = this.flags[key as keyof AFFINE_FLAGS].value;
if (value !== undefined) {
workspace.docCollection.awarenessStore.setFlag(flag.bsFlag, value);
}
}
}
}
setupRestartListener() {
this.flags.enable_ai.$.pipe(distinctUntilChanged(), skip(1)).subscribe(
() => {
@@ -1,4 +1,4 @@
import type { BlockSuiteFlags } from '@blocksuite/affine/global/types';
import type { BlockSuiteFlags } from '@blocksuite/affine/blocks';
type FeedbackType = 'discord' | 'email' | 'github';
@@ -1,3 +1,4 @@
import { SpecProvider } from '@blocksuite/affine/blocks';
import { type Disposable, Slot } from '@blocksuite/affine/global/utils';
import {
type AwarenessStore,
@@ -283,13 +284,18 @@ export class DocImpl implements Doc {
return this._docMap[readonlyKey].get(key) as Store;
}
const storeExtensions = SpecProvider.getInstance().getSpec('store');
const extensionSet = new Set(
storeExtensions.value.concat(extensions ?? [])
);
const doc = new Store({
doc: this,
schema: this.workspace.schema,
readonly,
query,
provider,
extensions,
extensions: Array.from(extensionSet),
});
this._docMap[readonlyKey].set(key, doc);
@@ -34,22 +34,6 @@ type WorkspaceOptions = {
};
const FLAGS_PRESET = {
enable_synced_doc_block: false,
enable_pie_menu: false,
enable_database_number_formatting: false,
enable_database_attachment_note: false,
enable_database_full_width: false,
enable_block_query: false,
enable_lasso_tool: false,
enable_edgeless_text: true,
enable_ai_onboarding: false,
enable_ai_chat_block: false,
enable_color_picker: false,
enable_mind_map_import: false,
enable_advanced_block_visibility: false,
enable_shape_shadow_blur: false,
enable_mobile_keyboard_toolbar: false,
enable_mobile_linked_doc_menu: false,
readonly: {},
} satisfies BlockSuiteFlags;