From ffab2f8dd86416b505a2047ddf49fcc380fda62e Mon Sep 17 00:00:00 2001 From: Jonathan Poltak Samosir Date: Wed, 19 Jun 2024 16:47:19 +0700 Subject: [PATCH] Greatly improve perf of dragging list around sidebar - If you dragged a list rapidly around the sidebar fast enough, the actions would form a queue and sequentially happen with a noticeable delay. This greatly improves that. - Main change is moving the setTimeout(mutation, 0) to the top level and not performing the mutation if nothing gets changed --- src/dashboard-refactor/index.tsx | 22 +++++++++++++++---- .../lists-sidebar/components/sidebar-item.tsx | 12 +--------- .../lists-sidebar/index.tsx | 11 +--------- src/dashboard-refactor/logic.ts | 6 ++++- src/dashboard-refactor/types.ts | 5 +++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/dashboard-refactor/index.tsx b/src/dashboard-refactor/index.tsx index 3ced7efb85..5d04549005 100644 --- a/src/dashboard-refactor/index.tsx +++ b/src/dashboard-refactor/index.tsx @@ -812,12 +812,26 @@ export class DashboardContainer extends StatefulUIElement< onListDragEnd={(listId) => (e) => this.processEvent('dropList', { listId })} initDropReceivingState={(listId) => ({ - onDragEnter: () => - this.processEvent('setDragOverListId', { listId }), - onDragLeave: () => + onDragEnter: (e) => { + e.preventDefault() + e.stopPropagation() + // Needed to push this op back on the event queue, so it fires after the previous + //  list item's `onDropLeave` event + setTimeout( + () => + this.processEvent('setDragOverListId', { + listId, + }), + 0, + ) + }, + onDragLeave: (e) => { + e.preventDefault() + e.stopPropagation() this.processEvent('setDragOverListId', { listId: undefined, - }), + }) + }, onDrop: (dataTransfer) => this.processEvent('dropOnListItem', { listId, diff --git a/src/dashboard-refactor/lists-sidebar/components/sidebar-item.tsx b/src/dashboard-refactor/lists-sidebar/components/sidebar-item.tsx index 927939ee38..5957a3a553 100644 --- a/src/dashboard-refactor/lists-sidebar/components/sidebar-item.tsx +++ b/src/dashboard-refactor/lists-sidebar/components/sidebar-item.tsx @@ -1,8 +1,6 @@ import React from 'react' import { fonts } from 'src/dashboard-refactor/styles' import styled, { css } from 'styled-components' -import Icon from '@worldbrain/memex-common/lib/common-ui/components/icon' -import { TooltipBox } from '@worldbrain/memex-common/lib/common-ui/components/tooltip-box' import type { DropReceivingState } from 'src/dashboard-refactor/types' export interface Props { @@ -38,14 +36,6 @@ export default class ListsSidebarItem extends React.PureComponent< > { state: State = { isHovering: false, canDisableHover: false } - private handleDragEnter: React.DragEventHandler = (e) => { - e.preventDefault() - e.stopPropagation() - // Needed to push this op back on the event queue, so it fires after the previous - //  list item's `onDropLeave` event - setTimeout(() => this.props.dropReceivingState?.onDragEnter(), 0) - } - private handleDrop: React.DragEventHandler = (e) => { e.preventDefault() if (!this.props.dropReceivingState?.canReceiveDroppedItems) { @@ -75,7 +65,7 @@ export default class ListsSidebarItem extends React.PureComponent< }) }} spaceSidebarWidth={this.props.spaceSidebarWidth} - onDragEnter={this.handleDragEnter} + onDragEnter={this.props.dropReceivingState?.onDragEnter} onDragLeave={this.props.dropReceivingState?.onDragLeave} onDragOver={(e) => { e.preventDefault() diff --git a/src/dashboard-refactor/lists-sidebar/index.tsx b/src/dashboard-refactor/lists-sidebar/index.tsx index 0afb658e62..f82c9365df 100644 --- a/src/dashboard-refactor/lists-sidebar/index.tsx +++ b/src/dashboard-refactor/lists-sidebar/index.tsx @@ -116,16 +116,7 @@ export default class ListsSidebar extends PureComponent { { - e.preventDefault() - e.stopPropagation() - // Needed to push this op back on the event queue, so it fires after the previous - //  list item's `onDropLeave` event - setTimeout( - () => reorderLineDropReceivingState.onDragEnter(), - 0, - ) - }} + onDragEnter={reorderLineDropReceivingState.onDragEnter} onDragLeave={reorderLineDropReceivingState.onDragLeave} onDragOver={(e: React.DragEvent) => { e.preventDefault() diff --git a/src/dashboard-refactor/logic.ts b/src/dashboard-refactor/logic.ts index ff2ed034a7..b090b85c79 100644 --- a/src/dashboard-refactor/logic.ts +++ b/src/dashboard-refactor/logic.ts @@ -4382,9 +4382,13 @@ export class DashboardLogic extends UILogic { }) } - setDragOverListId: EventHandler<'setDragOverListId'> = async ({ + setDragOverListId: EventHandler<'setDragOverListId'> = ({ event, + previousState, }) => { + if (event.listId === previousState.listsSidebar.dragOverListId) { + return + } this.emitMutation({ listsSidebar: { dragOverListId: { $set: event.listId } }, }) diff --git a/src/dashboard-refactor/types.ts b/src/dashboard-refactor/types.ts index 0a3267079b..aad7d9fd79 100644 --- a/src/dashboard-refactor/types.ts +++ b/src/dashboard-refactor/types.ts @@ -52,6 +52,7 @@ import type { SpaceSearchSuggestion } from '@worldbrain/memex-common/lib/editor' import type { HighlightColor } from '@worldbrain/memex-common/lib/common-ui/components/highlightColorPicker/types' import type { BulkEditCollection } from 'src/bulk-edit/types' import type { PersonalCloudRemoteInterface } from 'src/personal-cloud/background/types' +import type { DragEventHandler } from 'react' export interface RootState { loadState: TaskState @@ -152,8 +153,8 @@ export interface DropReceivingState { wasPageDropped?: boolean canReceiveDroppedItems?: boolean onDrop(dataTransfer: DataTransfer): void - onDragEnter(): void - onDragLeave(): void + onDragEnter: DragEventHandler + onDragLeave: DragEventHandler } export interface SearchResultTextPart {