From 2192f28500353354d464f9086fe72f3818630ed1 Mon Sep 17 00:00:00 2001 From: doodlewind <7312949+doodlewind@users.noreply.github.com> Date: Mon, 26 May 2025 01:16:32 +0000 Subject: [PATCH] fix(editor): allow space-drag in presentation mode (#12501) ### TL;DR Fix presentation mode space-drag interaction by disabling black background during panning and properly restoring presentation state. ### What changed? - Modified how the presentation tool handles state restoration after panning - Disabled black background during space-drag and middle-mouse panning in presentation mode - Fixed tool state management to properly restore presentation mode after space panning - Added direct modification of the current tool's activated options instead of triggering a full tool change ### How to test? 1. Create a frame in edgeless mode 2. Enter presentation mode 3. Press space and drag to pan around 4. Verify the black background disappears during panning 5. Verify presentation mode is properly restored after releasing space 6. Try the same with middle-mouse button dragging ### Why make this change? The black background in presentation mode was causing visibility issues during panning operations. Additionally, the presentation state wasn't being properly restored after space-drag panning. These changes improve the user experience by making content visible during navigation while maintaining the presentation mode state. ## Summary by CodeRabbit - **New Features** - Presentation mode now automatically hides the black background overlay when dragging with the space key or middle mouse button, improving visibility during navigation. - **Bug Fixes** - Improved handling of tool switching after panning in presentation mode, ensuring smoother transitions and state restoration. - **Tests** - Added an end-to-end test to verify that the black background is hidden during space-drag actions in presentation mode. --- .../edgeless-toolbar/presentation-toolbar.ts | 9 ++--- .../root/src/edgeless/edgeless-keyboard.ts | 35 +++++++++++++------ .../affine/gfx/pointer/src/tools/pan-tool.ts | 9 +++++ .../e2e/edgeless/presentation.spec.ts | 29 +++++++++++++++ 4 files changed, 67 insertions(+), 15 deletions(-) diff --git a/blocksuite/affine/blocks/frame/src/edgeless-toolbar/presentation-toolbar.ts b/blocksuite/affine/blocks/frame/src/edgeless-toolbar/presentation-toolbar.ts index 3c17b4ce24..0aae764e4b 100644 --- a/blocksuite/affine/blocks/frame/src/edgeless-toolbar/presentation-toolbar.ts +++ b/blocksuite/affine/blocks/frame/src/edgeless-toolbar/presentation-toolbar.ts @@ -205,10 +205,11 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin( !forceMove ) { // Clear the flag so future navigations behave normally - this.gfx.tool.setTool(PresentTool, { - ...toolOptions, - restoredAfterPan: false, - }); + // Here we modify the tool's activated option to avoid triggering setTool update + const currentTool = this.gfx.tool.currentTool$.peek(); + if (currentTool?.activatedOption) { + currentTool.activatedOption.restoredAfterPan = false; + } return; } diff --git a/blocksuite/affine/blocks/root/src/edgeless/edgeless-keyboard.ts b/blocksuite/affine/blocks/root/src/edgeless/edgeless-keyboard.ts index e03a05a5cf..a2fa08c075 100644 --- a/blocksuite/affine/blocks/root/src/edgeless/edgeless-keyboard.ts +++ b/blocksuite/affine/blocks/root/src/edgeless/edgeless-keyboard.ts @@ -1,6 +1,9 @@ import { insertLinkByQuickSearchCommand } from '@blocksuite/affine-block-bookmark'; import { EdgelessTextBlockComponent } from '@blocksuite/affine-block-edgeless-text'; -import { FrameTool } from '@blocksuite/affine-block-frame'; +import { + FrameTool, + type PresentToolOption, +} from '@blocksuite/affine-block-frame'; import { DefaultTool, EdgelessLegacySlotIdentifier, @@ -472,9 +475,6 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { const selection = gfx.selection; if (event.code === 'Space' && !event.repeat) { - const currentToolName = - this.rootComponent.gfx.tool.currentToolName$.peek(); - if (currentToolName === 'frameNavigator') return false; this._space(event); } else if ( !selection.editing && @@ -512,9 +512,6 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { ctx => { const event = ctx.get('keyboardState').raw; if (event.code === 'Space' && !event.repeat) { - const currentToolName = - this.rootComponent.gfx.tool.currentToolName$.peek(); - if (currentToolName === 'frameNavigator') return false; this._space(event); } return false; @@ -712,10 +709,18 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { const revertToPrevTool = (ev: KeyboardEvent) => { if (ev.code === 'Space') { - this._setEdgelessTool( - (currentTool as DefaultTool).constructor as typeof DefaultTool, - currentTool?.activatedOption - ); + const toolConstructor = currentTool.constructor as typeof DefaultTool; + let finalOptions = currentTool?.activatedOption; + + // Handle frameNavigator (PresentTool) restoration after space pan + if (currentTool.toolName === 'frameNavigator') { + finalOptions = { + ...currentTool?.activatedOption, + restoredAfterPan: true, + } as PresentToolOption; + } + + this._setEdgelessTool(toolConstructor, finalOptions); selection.set(currentSel); document.removeEventListener('keyup', revertToPrevTool, false); } @@ -728,6 +733,14 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { ) { return; } + + // If in presentation mode, disable black background during space drag + if (currentTool.toolName === 'frameNavigator') { + this.slots.navigatorSettingUpdated.next({ + blackBackground: false, + }); + } + this._setEdgelessTool(PanTool, { panning: false }); this.std.event.disposables.addFromEvent( diff --git a/blocksuite/affine/gfx/pointer/src/tools/pan-tool.ts b/blocksuite/affine/gfx/pointer/src/tools/pan-tool.ts index 66833c0159..8cbdd642dd 100644 --- a/blocksuite/affine/gfx/pointer/src/tools/pan-tool.ts +++ b/blocksuite/affine/gfx/pointer/src/tools/pan-tool.ts @@ -1,3 +1,4 @@ +import { EdgelessLegacySlotIdentifier } from '@blocksuite/affine-block-surface'; import { on } from '@blocksuite/affine-shared/utils'; import type { PointerEventState } from '@blocksuite/std'; import { BaseTool, MouseButton, type ToolOptions } from '@blocksuite/std/gfx'; @@ -84,6 +85,14 @@ export class PanTool extends BaseTool { this.gfx.selection.set(selectionToRestore); }; + // If in presentation mode, disable black background after middle mouse drag + if (currentTool.toolType?.toolName === 'frameNavigator') { + const slots = this.std.get(EdgelessLegacySlotIdentifier); + slots.navigatorSettingUpdated.next({ + blackBackground: false, + }); + } + this.controller.setTool(PanTool, { panning: true, }); diff --git a/tests/blocksuite/e2e/edgeless/presentation.spec.ts b/tests/blocksuite/e2e/edgeless/presentation.spec.ts index 743eb9bee1..3bbadb7f59 100644 --- a/tests/blocksuite/e2e/edgeless/presentation.spec.ts +++ b/tests/blocksuite/e2e/edgeless/presentation.spec.ts @@ -313,4 +313,33 @@ test.describe('presentation', () => { await prevButton.click(); await expect(note).toBeVisible(); }); + + test('should disable black background when space+drag in presentation mode', async ({ + page, + }) => { + await edgelessCommonSetup(page); + await createNote(page, [300, 100], 'hello'); + await setEdgelessTool(page, 'frame'); + await dragBetweenViewCoords(page, [240, 0], [800, 200]); + + expect(await page.locator('affine-frame').count()).toBe(1); + await enterPresentationMode(page); + await waitNextFrame(page, 300); + + await assertEdgelessTool(page, 'frameNavigator'); + + // Verify black background is initially visible + const navigatorBlackBackground = page.locator( + '.edgeless-navigator-black-background' + ); + await expect(navigatorBlackBackground).toBeVisible(); + + // Press space and drag to trigger the black background disable logic + await page.keyboard.down('Space'); + await dragBetweenViewCoords(page, [400, 300], [500, 400]); + await page.keyboard.up('Space'); + + await waitNextFrame(page, 100); + await expect(navigatorBlackBackground).toBeHidden(); + }); });