From c30b3749de323776981066196f9f0e7632eb3143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Hillerstr=C3=B6m?= Date: Sun, 22 Dec 2024 22:22:42 +0100 Subject: [PATCH 1/3] [UI] Fix some bugs with drag and drop --- ui/core/components/pickers/list_picker.tsx | 149 +++++++++++++-------- 1 file changed, 92 insertions(+), 57 deletions(-) diff --git a/ui/core/components/pickers/list_picker.tsx b/ui/core/components/pickers/list_picker.tsx index 132b48d7ac..8af8674722 100644 --- a/ui/core/components/pickers/list_picker.tsx +++ b/ui/core/components/pickers/list_picker.tsx @@ -163,7 +163,7 @@ export class ListPicker extends Input extends Input { @@ -196,13 +196,13 @@ export class ListPicker extends Input extends Input { moveButtonTooltip?.destroy(); }); - + this.addHoverListeners(moveButton); moveButton.addEventListener( @@ -342,11 +342,33 @@ export class ListPicker extends Input { - return !curDragData || - curDragData.listPicker.config.itemLabel !== this.config.itemLabel || - (this.config.itemLabel === 'Action' && curDragData.listPicker !== this); + + const droppingActionOnOtherList = () => curDragData && this.config.itemLabel === 'Action' && curDragData.listPicker !== this; + const targetIsSelf = () => curDragData && curDragData.listPicker === this && curDragData.item.idx === index; + const targetIsChild = () => curDragData && curDragData.item.elem.contains(itemContainer); + + const invalidDropTarget = (checkSelf = true, checkForActions = true) => { + // Only allow dropping on the same type of list, Value -> Value, Action -> Action + if (!curDragData || curDragData.listPicker.config.itemLabel !== this.config.itemLabel) { + return true; + } + + // Only allow dropping Actions within the same list + if (checkForActions && droppingActionOnOtherList()) { + return true; + } + + // Just skip trying to drop on itself? + if (checkSelf && targetIsSelf()) { + return true; + } + + // Can't drop within itself + if (checkSelf && targetIsChild()) { + return true; + } + + return false; }; let dragEnterCounter = 0; @@ -382,9 +404,10 @@ export class ListPicker extends Input { if (invalidDropTarget()) { - if (curDragData && this.config.itemLabel === 'Action' && curDragData.listPicker !== this) { + if (droppingActionOnOtherList() || targetIsSelf()) { event.dataTransfer!.dropEffect = 'none'; } + return; } event.dataTransfer!.dropEffect = 'move'; @@ -393,7 +416,7 @@ export class ListPicker extends Input { if (!curDragData) { return; @@ -405,12 +428,12 @@ export class ListPicker extends Input { - if (invalidDropTarget()) { + if (invalidDropTarget(false)) { return; } event.stopPropagation(); @@ -423,7 +446,11 @@ export class ListPicker extends Input { - if (!curDragData || curDragData.listPicker.config.itemLabel !== this.config.itemLabel) { + if (!curDragData || invalidDropTarget(true, false)) { + if (targetIsSelf()) { + event.stopPropagation(); + cleanupAfterDrag(); + } return; } event.stopPropagation(); @@ -452,9 +479,9 @@ export class ListPicker extends Input extends Input { popover.classList.remove('hover'); popover.hidePopover(); }, - { signal: this.signal } - ) + { signal: this.signal }, + ); } this.itemPickerPairs.push(item); @@ -500,18 +527,27 @@ export class ListPicker extends Input, getValidations: (player: Player) => Array) { @@ -545,47 +581,46 @@ export class ListPicker extends Input { - const logLevel = curr.logLevel; - maxLogLevel = Math.max(logLevel, maxLogLevel); - - const group = groups.get(logLevel) - if (group) { - group.push(curr.validation); - } else { - groups.set(logLevel, [curr.validation]) - } + const groupedValidations = formattedValidations.reduce((groups, curr) => { + const logLevel = curr.logLevel; + maxLogLevel = Math.max(logLevel, maxLogLevel); - return groups; - }, - new Map(), - ); + const group = groups.get(logLevel); + if (group) { + group.push(curr.validation); + } else { + groups.set(logLevel, [curr.validation]); + } + + return groups; + }, new Map()); for (const [_logLevel, displayData] of this.logLevelDisplayData) { iconElem!.classList.remove(displayData.icon); } // New icon is set outside loop so log levels can share the same icon without risk of removing each other - const newIcon = this.logLevelDisplayData.get(maxLogLevel)?.icon + const newIcon = this.logLevelDisplayData.get(maxLogLevel)?.icon; if (newIcon) { iconElem!.classList.add(newIcon); } for (const [key, value] of Object.entries(LogLevel)) { - validationElem.classList[value === maxLogLevel ? "add" : "remove"](`apl-validation-${key.toLowerCase()}`) + validationElem.classList[value === maxLogLevel ? 'add' : 'remove'](`apl-validation-${key.toLowerCase()}`); } - let content = ""; + let content = ''; for (const [logLevel, validations] of groupedValidations) { - content = content + ` + content = + content + + `

${this.logLevelDisplayData.get(logLevel)?.header}

    ${validations.map(v => `
  • ${v}
  • `).join('')}
`; - }; - validationTooltip.setContent(content) + } + validationTooltip.setContent(content); } }; updateValidations(); From 67d9ca2d3f1b4975ac10b7131ee8a589b6f1743d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Hillerstr=C3=B6m?= Date: Sun, 22 Dec 2024 22:27:12 +0100 Subject: [PATCH 2/3] [UI] Drop after targeted element if mouse pointer has passed halfway --- ui/core/components/pickers/list_picker.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/core/components/pickers/list_picker.tsx b/ui/core/components/pickers/list_picker.tsx index 8af8674722..e21c79e347 100644 --- a/ui/core/components/pickers/list_picker.tsx +++ b/ui/core/components/pickers/list_picker.tsx @@ -457,7 +457,13 @@ export class ListPicker extends Input targetRect.top + targetRect.height / 2) { + dstIdx++; + } + const newList = this.config.getValue(this.modObject); let arrElem; From d1247fbc47eb1d499b0ca05c012efdea30be33a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Hillerstr=C3=B6m?= Date: Sun, 22 Dec 2024 22:31:13 +0100 Subject: [PATCH 3/3] [UI] Move dragged element completely out of the way --- ui/core/components/pickers/list_picker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/core/components/pickers/list_picker.tsx b/ui/core/components/pickers/list_picker.tsx index e21c79e347..1d0271d548 100644 --- a/ui/core/components/pickers/list_picker.tsx +++ b/ui/core/components/pickers/list_picker.tsx @@ -330,7 +330,7 @@ export class ListPicker extends Input { if (event.target == moveButton) { const popoverRect = popover.getBoundingClientRect(); - event.dataTransfer!.setDragImage(itemContainer, popoverRect.width, popoverRect.height / 2); + event.dataTransfer!.setDragImage(itemContainer, 0, popoverRect.height / 2); event.dataTransfer!.dropEffect = 'move'; event.dataTransfer!.effectAllowed = 'move'; itemContainer.classList.add('dragfrom');