fix: color of canvas element under embed whiteboard is wrong (#8712)

Fix issue [BS-1762](https://linear.app/affine-design/issue/BS-1762). Related [PR](https://github.com/toeverything/blocksuite/pull/8677) in Blocksuite.

`light` whiteboard with embedded `dark` whiteboard:
![截屏2024-11-05 22.39.18.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/42319032-0940-4a67-b12b-64aeec9c49a6.png)

`dark` whiteboard with embedded `light` whiteboard:
![截屏2024-11-05 22.43.36.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/63c5c747-73dc-4d4b-89c7-281d4bf20fcc.png)

`light` doc with `dark` frame:
![截屏2024-11-05 22.40.01.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/b1eae95f-41aa-4093-8fa1-5641578e8f4e.png)
This commit is contained in:
akumatus 2024-11-12 08:03:05 +00:00
parent 98bdf25844
commit e2b221a451
No known key found for this signature in database
GPG Key ID: D1FD534C6C29FE19
5 changed files with 132 additions and 27 deletions

View File

@ -24,7 +24,6 @@ import {
type DocCustomPropertyInfo, type DocCustomPropertyInfo,
DocService, DocService,
DocsService, DocsService,
FeatureFlagService,
useFramework, useFramework,
useLiveData, useLiveData,
useService, useService,
@ -50,6 +49,7 @@ import {
} from '../../doc-properties'; } from '../../doc-properties';
import { BiDirectionalLinkPanel } from './bi-directional-link-panel'; import { BiDirectionalLinkPanel } from './bi-directional-link-panel';
import { BlocksuiteEditorJournalDocTitle } from './journal-doc-title'; import { BlocksuiteEditorJournalDocTitle } from './journal-doc-title';
import { extendEdgelessPreviewSpec } from './specs/custom/root-block';
import { import {
patchDocModeService, patchDocModeService,
patchEdgelessClipboard, patchEdgelessClipboard,
@ -96,14 +96,12 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
docsService, docsService,
editorService, editorService,
workspaceService, workspaceService,
featureFlagService,
} = useServices({ } = useServices({
PeekViewService, PeekViewService,
DocService, DocService,
DocsService, DocsService,
WorkspaceService, WorkspaceService,
EditorService, EditorService,
FeatureFlagService,
}); });
const framework = useFramework(); const framework = useFramework();
const referenceRenderer: ReferenceReactRenderer = useMemo(() => { const referenceRenderer: ReferenceReactRenderer = useMemo(() => {
@ -130,12 +128,15 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
}; };
}, [workspaceService]); }, [workspaceService]);
useMemo(() => {
extendEdgelessPreviewSpec(framework);
}, [framework]);
const specs = useMemo(() => { const specs = useMemo(() => {
const enableAI = featureFlagService.flags.enable_ai.value;
return mode === 'edgeless' return mode === 'edgeless'
? createEdgelessModeSpecs(framework, !!enableAI) ? createEdgelessModeSpecs(framework)
: createPageModeSpecs(framework, !!enableAI); : createPageModeSpecs(framework);
}, [featureFlagService.flags.enable_ai.value, mode, framework]); }, [mode, framework]);
const confirmModal = useConfirmModal(); const confirmModal = useConfirmModal();
const patchedSpecs = useMemo(() => { const patchedSpecs = useMemo(() => {

View File

@ -30,11 +30,13 @@ import {
import { import {
createSignalFromObservable, createSignalFromObservable,
type Signal, type Signal,
SpecProvider,
} from '@blocksuite/affine-shared/utils'; } from '@blocksuite/affine-shared/utils';
import type { Container } from '@blocksuite/global/di'; import type { Container } from '@blocksuite/global/di';
import { import {
DocService, DocService,
DocsService, DocsService,
FeatureFlagService,
type FrameworkProvider, type FrameworkProvider,
} from '@toeverything/infra'; } from '@toeverything/infra';
import type { Observable } from 'rxjs'; import type { Observable } from 'rxjs';
@ -60,7 +62,7 @@ function getTelemetryExtension(): ExtensionType {
}; };
} }
function createThemeExtension(framework: FrameworkProvider) { function getThemeExtension(framework: FrameworkProvider) {
class AffineThemeExtension class AffineThemeExtension
extends LifeCycleWatcher extends LifeCycleWatcher
implements ThemeExtension implements ThemeExtension
@ -153,14 +155,32 @@ function getEditorConfigExtension(
]; ];
} }
export const extendEdgelessPreviewSpec = (function () {
let _extension: ExtensionType;
let _framework: FrameworkProvider;
return function (framework: FrameworkProvider) {
if (framework === _framework && _extension) {
return _extension;
} else {
_extension &&
SpecProvider.getInstance().omitSpec('edgeless:preview', _extension);
_extension = getThemeExtension(framework);
_framework = framework;
SpecProvider.getInstance().extendSpec('edgeless:preview', [_extension]);
return _extension;
}
};
})();
export function createPageRootBlockSpec( export function createPageRootBlockSpec(
framework: FrameworkProvider, framework: FrameworkProvider
enableAI: boolean
): ExtensionType[] { ): ExtensionType[] {
const featureFlagService = framework.get(FeatureFlagService);
const enableAI = featureFlagService.flags.enable_ai.value;
return [ return [
enableAI ? AIPageRootBlockSpec : PageRootBlockSpec, enableAI ? AIPageRootBlockSpec : PageRootBlockSpec,
FontLoaderService, FontLoaderService,
createThemeExtension(framework), getThemeExtension(framework),
getFontConfigExtension(), getFontConfigExtension(),
getTelemetryExtension(), getTelemetryExtension(),
getEditorConfigExtension(framework), getEditorConfigExtension(framework),
@ -168,13 +188,14 @@ export function createPageRootBlockSpec(
} }
export function createEdgelessRootBlockSpec( export function createEdgelessRootBlockSpec(
framework: FrameworkProvider, framework: FrameworkProvider
enableAI: boolean
): ExtensionType[] { ): ExtensionType[] {
const featureFlagService = framework.get(FeatureFlagService);
const enableAI = featureFlagService.flags.enable_ai.value;
return [ return [
enableAI ? AIEdgelessRootBlockSpec : EdgelessRootBlockSpec, enableAI ? AIEdgelessRootBlockSpec : EdgelessRootBlockSpec,
FontLoaderService, FontLoaderService,
createThemeExtension(framework), getThemeExtension(framework),
EdgelessToolExtension, EdgelessToolExtension,
EdgelessBuiltInManager, EdgelessBuiltInManager,
getFontConfigExtension(), getFontConfigExtension(),

View File

@ -10,15 +10,19 @@ import {
EdgelessTextBlockSpec, EdgelessTextBlockSpec,
FrameBlockSpec, FrameBlockSpec,
} from '@blocksuite/affine/blocks'; } from '@blocksuite/affine/blocks';
import type { FrameworkProvider } from '@toeverything/infra'; import {
FeatureFlagService,
type FrameworkProvider,
} from '@toeverything/infra';
import { AIBlockSpecs, DefaultBlockSpecs } from './common'; import { AIBlockSpecs, DefaultBlockSpecs } from './common';
import { createEdgelessRootBlockSpec } from './custom/root-block'; import { createEdgelessRootBlockSpec } from './custom/root-block';
export function createEdgelessModeSpecs( export function createEdgelessModeSpecs(
framework: FrameworkProvider, framework: FrameworkProvider
enableAI: boolean
): ExtensionType[] { ): ExtensionType[] {
const featureFlagService = framework.get(FeatureFlagService);
const enableAI = featureFlagService.flags.enable_ai.value;
return [ return [
...(enableAI ? AIBlockSpecs : DefaultBlockSpecs), ...(enableAI ? AIBlockSpecs : DefaultBlockSpecs),
EdgelessSurfaceBlockSpec, EdgelessSurfaceBlockSpec,
@ -27,7 +31,7 @@ export function createEdgelessModeSpecs(
EdgelessTextBlockSpec, EdgelessTextBlockSpec,
EdgelessNoteBlockSpec, EdgelessNoteBlockSpec,
// special // special
createEdgelessRootBlockSpec(framework, enableAI), createEdgelessRootBlockSpec(framework),
].flat(); ].flat();
} }

View File

@ -4,21 +4,25 @@ import {
PageSurfaceBlockSpec, PageSurfaceBlockSpec,
PageSurfaceRefBlockSpec, PageSurfaceRefBlockSpec,
} from '@blocksuite/affine/blocks'; } from '@blocksuite/affine/blocks';
import { type FrameworkProvider } from '@toeverything/infra'; import {
FeatureFlagService,
type FrameworkProvider,
} from '@toeverything/infra';
import { AIBlockSpecs, DefaultBlockSpecs } from './common'; import { AIBlockSpecs, DefaultBlockSpecs } from './common';
import { createPageRootBlockSpec } from './custom/root-block'; import { createPageRootBlockSpec } from './custom/root-block';
export function createPageModeSpecs( export function createPageModeSpecs(
framework: FrameworkProvider, framework: FrameworkProvider
enableAI: boolean
): ExtensionType[] { ): ExtensionType[] {
const featureFlagService = framework.get(FeatureFlagService);
const enableAI = featureFlagService.flags.enable_ai.value;
return [ return [
...(enableAI ? AIBlockSpecs : DefaultBlockSpecs), ...(enableAI ? AIBlockSpecs : DefaultBlockSpecs),
PageSurfaceBlockSpec, PageSurfaceBlockSpec,
PageSurfaceRefBlockSpec, PageSurfaceRefBlockSpec,
NoteBlockSpec, NoteBlockSpec,
// special // special
createPageRootBlockSpec(framework, enableAI), createPageRootBlockSpec(framework),
].flat(); ].flat();
} }

View File

@ -1,16 +1,33 @@
import { Skeleton } from '@affine/component'; import { Skeleton } from '@affine/component';
import type { EditorSettingSchema } from '@affine/core/modules/editor-setting'; import type { EditorSettingSchema } from '@affine/core/modules/editor-setting';
import { EditorSettingService } from '@affine/core/modules/editor-setting'; import { EditorSettingService } from '@affine/core/modules/editor-setting';
import { AppThemeService } from '@affine/core/modules/theme';
import type { EditorHost } from '@blocksuite/affine/block-std'; import type { EditorHost } from '@blocksuite/affine/block-std';
import { BlockStdScope } from '@blocksuite/affine/block-std'; import {
BlockStdScope,
LifeCycleWatcher,
StdIdentifier,
} from '@blocksuite/affine/block-std';
import type { GfxPrimitiveElementModel } from '@blocksuite/affine/block-std/gfx'; import type { GfxPrimitiveElementModel } from '@blocksuite/affine/block-std/gfx';
import type { EdgelessRootService } from '@blocksuite/affine/blocks'; import type {
import { SpecProvider } from '@blocksuite/affine/blocks'; EdgelessRootService,
ThemeExtension,
} from '@blocksuite/affine/blocks';
import {
ColorScheme,
SpecProvider,
ThemeExtensionIdentifier,
} from '@blocksuite/affine/blocks';
import { Bound } from '@blocksuite/affine/global/utils'; import { Bound } from '@blocksuite/affine/global/utils';
import type { Block, Doc } from '@blocksuite/affine/store'; import type { Block, Doc } from '@blocksuite/affine/store';
import { createSignalFromObservable } from '@blocksuite/affine-shared/utils';
import type { Container } from '@blocksuite/global/di';
import type { Signal } from '@preact/signals-core';
import type { FrameworkProvider } from '@toeverything/infra';
import { useFramework } from '@toeverything/infra'; import { useFramework } from '@toeverything/infra';
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useRef } from 'react'; import { useCallback, useEffect, useRef } from 'react';
import type { Observable } from 'rxjs';
import { map, pairwise } from 'rxjs'; import { map, pairwise } from 'rxjs';
import { import {
@ -74,7 +91,10 @@ export const EdgelessSnapshot = (props: Props) => {
const editorHost = new BlockStdScope({ const editorHost = new BlockStdScope({
doc, doc,
extensions: SpecProvider.getInstance().getSpec('edgeless:preview').value, extensions: [
...SpecProvider.getInstance().getSpec('edgeless:preview').value,
getThemeExtension(framework),
],
}).render(); }).render();
docRef.current = doc; docRef.current = doc;
editorHostRef.current?.remove(); editorHostRef.current?.remove();
@ -106,7 +126,7 @@ export const EdgelessSnapshot = (props: Props) => {
// append to dom node // append to dom node
wrapperRef.current.append(editorHost); wrapperRef.current.append(editorHost);
}, [docName, firstUpdate, updateElements]); }, [docName, firstUpdate, framework, updateElements]);
useEffect(() => { useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises
@ -150,3 +170,58 @@ export const EdgelessSnapshot = (props: Props) => {
</div> </div>
); );
}; };
function getThemeExtension(framework: FrameworkProvider) {
class AffineThemeExtension
extends LifeCycleWatcher
implements ThemeExtension
{
static override readonly key = 'affine-settings-theme';
private readonly theme: Signal<ColorScheme>;
protected readonly disposables: (() => void)[] = [];
static override setup(di: Container) {
super.setup(di);
di.override(ThemeExtensionIdentifier, AffineThemeExtension, [
StdIdentifier,
]);
}
constructor(std: BlockStdScope) {
super(std);
const theme$: Observable<ColorScheme> = framework
.get(AppThemeService)
.appTheme.theme$.map(theme => {
return theme === ColorScheme.Dark
? ColorScheme.Dark
: ColorScheme.Light;
});
const { signal, cleanup } = createSignalFromObservable<ColorScheme>(
theme$,
ColorScheme.Light
);
this.theme = signal;
this.disposables.push(cleanup);
}
getAppTheme() {
return this.theme;
}
getEdgelessTheme() {
return this.theme;
}
override unmounted() {
this.dispose();
}
dispose() {
this.disposables.forEach(dispose => dispose());
}
}
return AffineThemeExtension;
}