fix(editor): make table drag payload reliable

This commit is contained in:
t8y2
2026-05-30 09:42:12 +08:00
parent 548692f073
commit 879da4b86f
4 changed files with 100 additions and 15 deletions
@@ -26,6 +26,8 @@ import { extractIdentifierAt, isSqlKeyword, matchTable } from "@/lib/sqlNavigati
import { lineColumnToOffset, parseSqlErrorLocation } from "@/lib/sqlDiagnostics";
import {
DBX_TABLE_REFERENCE_MIME,
activeTableReferencePayloadValue,
clearActiveTableReferencePayload,
hasTableReferencePayloadType,
parseTableReferencePayload,
tableReferenceInsertText,
@@ -723,11 +725,14 @@ async function formatCurrentSql() {
}
function droppedTableReference(event: DragEvent) {
return parseTableReferencePayload(event.dataTransfer?.getData(DBX_TABLE_REFERENCE_MIME));
return (
activeTableReferencePayloadValue() ??
parseTableReferencePayload(event.dataTransfer?.getData(DBX_TABLE_REFERENCE_MIME))
);
}
function hasDroppedTableReference(event: DragEvent) {
return hasTableReferencePayloadType(event.dataTransfer?.types);
return !!activeTableReferencePayloadValue() || hasTableReferencePayloadType(event.dataTransfer?.types);
}
function insertDroppedTableReference(currentView: EditorViewType, event: DragEvent): boolean {
@@ -749,6 +754,7 @@ function insertDroppedTableReference(currentView: EditorViewType, event: DragEve
scrollIntoView: true,
userEvent: "input.drop",
});
clearActiveTableReferencePayload(payload);
currentView.focus();
return true;
}
@@ -60,8 +60,10 @@ import { canTreeNodeShowExpander, treeItemPaddingLeft } from "@/lib/sidebarTreeI
import { buildTableSelectSql } from "@/lib/tableSelectSql";
import {
DBX_TABLE_REFERENCE_MIME,
clearActiveTableReferencePayload,
createTableReferencePayload,
serializeTableReferencePayload,
setActiveTableReferencePayload,
tableReferenceInsertText,
} from "@/lib/queryEditorTableDrop";
import { editablePrimaryKeys, usesSyntheticRowIdKey } from "@/lib/tableEditing";
@@ -1803,9 +1805,11 @@ const canDragTableReference = computed(
!props.dragDisabled &&
(props.node.type === "table" || props.node.type === "view") &&
!!props.node.connectionId &&
!!props.node.database,
props.node.database != null,
);
let draggingTableReferencePayload: ReturnType<typeof createTableReferencePayload> = null;
function onTableReferenceDragStart(event: DragEvent) {
if (!canDragTableReference.value) return;
const payload = createTableReferencePayload({
@@ -1815,11 +1819,20 @@ function onTableReferenceDragStart(event: DragEvent) {
tableName: props.node.label,
databaseType: currentDatabaseType(),
});
if (!payload || !event.dataTransfer) return;
if (!payload) return;
draggingTableReferencePayload = payload;
setActiveTableReferencePayload(payload);
const insertText = tableReferenceInsertText(payload, currentDatabaseType());
event.dataTransfer.effectAllowed = "copy";
event.dataTransfer.setData(DBX_TABLE_REFERENCE_MIME, serializeTableReferencePayload(payload));
event.dataTransfer.setData("text/plain", insertText);
if (event.dataTransfer) {
event.dataTransfer.effectAllowed = "copy";
event.dataTransfer.setData(DBX_TABLE_REFERENCE_MIME, serializeTableReferencePayload(payload));
event.dataTransfer.setData("text/plain", insertText);
}
}
function onTableReferenceDragEnd() {
clearActiveTableReferencePayload(draggingTableReferencePayload);
draggingTableReferencePayload = null;
}
// ---- CustomContextMenu ----
@@ -2147,6 +2160,7 @@ function treeItemMenuItems(): ContextMenuItem[] {
@mousemove="isDropTarget ? updateTarget($event, node.id, node.type) : undefined"
@mouseleave="clearTarget(node.id)"
@dragstart="onTableReferenceDragStart"
@dragend="onTableReferenceDragEnd"
>
<div
v-if="showDropBefore"
+25 -8
View File
@@ -12,6 +12,8 @@ export interface QueryEditorTableReferencePayload {
databaseType?: DatabaseType;
}
let activeTableReferencePayload: QueryEditorTableReferencePayload | null = null;
export function createTableReferencePayload(options: {
connectionId?: string;
database?: string;
@@ -19,15 +21,16 @@ export function createTableReferencePayload(options: {
tableName?: string;
databaseType?: DatabaseType;
}): QueryEditorTableReferencePayload | null {
if (!options.connectionId || !options.database || !options.tableName) return null;
return {
if (!options.connectionId || options.database == null || !options.tableName) return null;
const payload: QueryEditorTableReferencePayload = {
kind: "dbx-table-reference",
connectionId: options.connectionId,
database: options.database,
schema: options.schema,
tableName: options.tableName,
databaseType: options.databaseType,
};
if (options.schema) payload.schema = options.schema;
if (options.databaseType) payload.databaseType = options.databaseType;
return payload;
}
export function serializeTableReferencePayload(payload: QueryEditorTableReferencePayload): string {
@@ -44,19 +47,19 @@ export function parseTableReferencePayload(value: string | undefined | null): Qu
typeof parsed.database !== "string" ||
typeof parsed.tableName !== "string" ||
!parsed.connectionId ||
!parsed.database ||
!parsed.tableName
) {
return null;
}
return {
const payload: QueryEditorTableReferencePayload = {
kind: "dbx-table-reference",
connectionId: parsed.connectionId,
database: parsed.database,
schema: typeof parsed.schema === "string" && parsed.schema ? parsed.schema : undefined,
tableName: parsed.tableName,
databaseType: parsed.databaseType,
};
if (typeof parsed.schema === "string" && parsed.schema) payload.schema = parsed.schema;
if (parsed.databaseType) payload.databaseType = parsed.databaseType;
return payload;
} catch {
return null;
}
@@ -70,6 +73,20 @@ export function hasTableReferencePayloadType(types: Iterable<string> | undefined
return false;
}
export function setActiveTableReferencePayload(payload: QueryEditorTableReferencePayload | null) {
activeTableReferencePayload = payload;
}
export function activeTableReferencePayloadValue(): QueryEditorTableReferencePayload | null {
return activeTableReferencePayload;
}
export function clearActiveTableReferencePayload(payload?: QueryEditorTableReferencePayload | null) {
if (!payload || activeTableReferencePayload === payload) {
activeTableReferencePayload = null;
}
}
export function tableReferenceInsertText(
payload: QueryEditorTableReferencePayload,
fallbackDatabaseType?: DatabaseType,