-
Notifications
You must be signed in to change notification settings - Fork 33
fix: DH-22093: Fix web UI freezing bug from grid-block-events #2646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1181,3 +1181,243 @@ describe('column separators', () => { | |||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| describe('grid-block-events cleanup', () => { | ||||||||||||||||||||||||
| const resizableTheme = { ...defaultTheme, allowColumnResize: true }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| function getColumnSeparatorX(columnIndex: VisibleIndex): number { | ||||||||||||||||||||||||
| const { rowHeaderWidth, columnWidth } = resizableTheme; | ||||||||||||||||||||||||
| return rowHeaderWidth + columnWidth * (columnIndex + 1) - 2; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| function getColumnHeaderY(): number { | ||||||||||||||||||||||||
| return Math.floor(resizableTheme.columnHeaderHeight / 2); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| function hasBlockEventsClass(): boolean { | ||||||||||||||||||||||||
| return document.documentElement.classList.contains('grid-block-events'); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| beforeEach(() => { | ||||||||||||||||||||||||
| // Ensure clean state before each test | ||||||||||||||||||||||||
| document.documentElement.classList.remove('grid-block-events'); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| afterEach(() => { | ||||||||||||||||||||||||
| // Clean up after each test | ||||||||||||||||||||||||
| document.documentElement.classList.remove('grid-block-events'); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| it('should remove grid-block-events after normal drag and mouse up', () => { | ||||||||||||||||||||||||
| const component = makeGridComponent(new MockGridModel(), resizableTheme); | ||||||||||||||||||||||||
| const separatorX = getColumnSeparatorX(0); | ||||||||||||||||||||||||
| const headerY = getColumnHeaderY(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| expect(hasBlockEventsClass()).toBe(false); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Start drag on column separator | ||||||||||||||||||||||||
| mouseDown(0, 0, component, {}, separatorX, headerY); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Drag to trigger handleMouseDrag which adds the class | ||||||||||||||||||||||||
| fireEvent.mouseMove(window, { | ||||||||||||||||||||||||
| clientX: separatorX + 50, | ||||||||||||||||||||||||
| clientY: headerY, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| expect(hasBlockEventsClass()).toBe(true); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Normal mouse up should clean up | ||||||||||||||||||||||||
| fireEvent.mouseUp(window, { | ||||||||||||||||||||||||
| clientX: separatorX + 50, | ||||||||||||||||||||||||
| clientY: headerY, | ||||||||||||||||||||||||
| button: 0, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| expect(hasBlockEventsClass()).toBe(false); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| it('should remove grid-block-events when right-clicking during drag (case 1)', () => { | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| it('should remove grid-block-events when right-clicking during drag (case 1)', () => { | |
| it('should keep grid-block-events after right-click during drag until left mouse up (case 1)', () => { |
Copilot
AI
Mar 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These comments describe behavior as a current bug ("BUG: Currently it doesn't...") but the implementation in this PR makes removeDocumentCursor() remove grid-block-events even when documentCursor is null. Please update/remove the bug explanation so the test documents the new expected behavior rather than the pre-fix state.
| // removeDocumentCursor should still clean up | |
| // BUG: Currently it doesn't because documentCursor is null and | |
| // the entire function body is guarded by `if (this.documentCursor != null)` | |
| component.removeDocumentCursor(); | |
| // After fix, this should be false | |
| // removeDocumentCursor should clean up grid-block-events | |
| // even if documentCursor is currently null | |
| component.removeDocumentCursor(); | |
| // grid-block-events should be removed after calling removeDocumentCursor |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -353,6 +353,10 @@ class Grid extends PureComponent<GridProps, GridState> { | |||||||||||||
| // blocked pointer events that would otherwise prevent cursor styling from showing | ||||||||||||||
| documentCursor: string | null; | ||||||||||||||
|
|
||||||||||||||
| // Track if this Grid instance added the grid-block-events class | ||||||||||||||
| // Used to ensure only the Grid that added the class removes it | ||||||||||||||
| hasAddedBlockEvents: boolean; | ||||||||||||||
|
|
||||||||||||||
| dragTimer: ReturnType<typeof setTimeout> | null; | ||||||||||||||
|
|
||||||||||||||
| keyHandlers: readonly KeyHandler[]; | ||||||||||||||
|
|
@@ -410,6 +414,7 @@ class Grid extends PureComponent<GridProps, GridState> { | |||||||||||||
| // Note: on document, not body so that cursor styling can be combined with | ||||||||||||||
| // blocked pointer events that would otherwise prevent cursor styling from showing | ||||||||||||||
| this.documentCursor = null; | ||||||||||||||
| this.hasAddedBlockEvents = false; | ||||||||||||||
|
|
||||||||||||||
| this.dragTimer = null; | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -1703,14 +1708,20 @@ class Grid extends PureComponent<GridProps, GridState> { | |||||||||||||
| document.documentElement.classList.add(this.documentCursor); | ||||||||||||||
| } | ||||||||||||||
| document.documentElement.classList.add('grid-block-events'); | ||||||||||||||
| this.hasAddedBlockEvents = true; | ||||||||||||||
|
Comment on lines
1710
to
+1711
|
||||||||||||||
| document.documentElement.classList.add('grid-block-events'); | |
| this.hasAddedBlockEvents = true; | |
| const docEl = document.documentElement; | |
| const hadBlockEventsClass = docEl.classList.contains('grid-block-events'); | |
| docEl.classList.add('grid-block-events'); | |
| this.hasAddedBlockEvents = !hadBlockEventsClass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getColumnSeparatorX/getColumnHeaderYhelpers are duplicated from the earlier "column separators" tests in this file. To reduce drift and make future updates easier, consider hoisting these helpers to a shared scope (or reusing the existing ones) instead of redefining them in eachdescribeblock.