fix(editor): sync gfx block transform update with RAF to prevent stale transform (#11322)

Close [BS-2866](https://linear.app/affine-design/issue/BS-2866/presentation-mode中的note消失)

## Problem
When using RequestAnimationFrame (RAF) for GFX block updates, there was a timing issue where the transform update would lag behind the RAF callback, causing the block to display with the previous frame's transform state.

## Solution
1. Refactored the block state management to use signals for better reactivity
2. Moved block visibility state management from `viewport-element.ts` to `gfx-block-component.ts`
3. Added `transformState$` signal to track block state
4. Synchronized transform updates with RAF using `effect` to ensure updates happen in the correct frame
5. Added test case to verify note visibility in presentation mode
This commit is contained in:
L-Sun
2025-03-31 12:47:01 +00:00
parent fec698fd8b
commit c9e14ac0db
3 changed files with 108 additions and 47 deletions

View File

@@ -8,8 +8,10 @@ import {
dragBetweenViewCoords,
edgelessCommonSetup,
enterPresentationMode,
getSelectedBound,
locatorPresentationToolbarButton,
resizeElementByHandle,
selectElementInEdgeless,
selectNoteInEdgeless,
setEdgelessTool,
Shape,
@@ -271,4 +273,44 @@ test.describe('presentation', () => {
const collapseButton = page.getByTestId('edgeless-note-collapse-button');
await expect(collapseButton).not.toBeVisible();
});
test('note should be visible when enter presentation mode', async ({
page,
}) => {
await enterPlaygroundRoom(page);
const { noteId } = await initEmptyEdgelessState(page);
await switchEditorMode(page);
await selectNoteInEdgeless(page, noteId);
const noteBound = await getSelectedBound(page);
await pressEscape(page, 3);
const frame1 = await createFrame(
page,
[noteBound[0] - 10, noteBound[1] - 10],
[noteBound[0] + noteBound[2] + 10, noteBound[1] + noteBound[3] + 10]
);
await selectElementInEdgeless(page, [frame1]);
const frame1Bound = await getSelectedBound(page);
await pressEscape(page);
await createFrame(
page,
[frame1Bound[0] + frame1Bound[2] + 10, frame1Bound[1]],
[frame1Bound[0] + 2 * frame1Bound[2], frame1Bound[1] + frame1Bound[3]]
);
await enterPresentationMode(page);
const nextButton = locatorPresentationToolbarButton(page, 'next');
const prevButton = locatorPresentationToolbarButton(page, 'previous');
const note = page.locator('affine-edgeless-note');
await expect(note).toBeVisible();
await nextButton.click();
await expect(note).toBeHidden();
await prevButton.click();
await expect(note).toBeVisible();
});
});