diff --git a/packages/main/src/listeners/listener.ts b/packages/main/src/listeners/listener.ts index acb65131..d130de8d 100644 --- a/packages/main/src/listeners/listener.ts +++ b/packages/main/src/listeners/listener.ts @@ -77,7 +77,14 @@ export class RuntimeListener { }); ipcMain.on(TOPICS.DROP_TAB, async (event, args) => { - console.log('tab dropped', args.tabId, args.frameTarget); + console.log('tab dropped', args.tabId, args.frameTarget, args.source); + if (this.draggedTab) { + console.log( + 'dragged tab', + this.draggedTab.tabId, + this.draggedTab.source, + ); + } let tabId: string | undefined; let source: string | undefined; if (this.draggedTab) { @@ -140,7 +147,7 @@ export class RuntimeListener { }); ipcMain.on(TOPICS.TEAR_OUT_TAB, async (event, args) => { - console.log('tab tear out', event, args.tabId, args.frameTarget); + console.log('tab tear out', args.tabId, args.frameTarget); let tabId: string | undefined; if (this.draggedTab) { diff --git a/packages/renderer/src/Frame.tsx b/packages/renderer/src/Frame.tsx index 5251c644..181afbe7 100644 --- a/packages/renderer/src/Frame.tsx +++ b/packages/renderer/src/Frame.tsx @@ -25,6 +25,11 @@ import { let draggedTab: string | null = null; +let tabDragTimeout: number = 0; + +//flag to indicate we are dragging and dropping tabs within the tabset - not tearing ouut +let internalDnD: boolean = false; + const darkTheme = createTheme({ palette: { mode: 'dark', @@ -184,6 +189,11 @@ export class Frame extends React.Component< const allowDrop = (ev: SyntheticDragEvent) => { ev.preventDefault(); + if (tabDragTimeout > 0) { + window.clearTimeout(tabDragTimeout); + tabDragTimeout = 0; + } + //internalDnD = false; }; const allowFrameDrop = (ev: SyntheticDragEvent) => { @@ -191,6 +201,8 @@ export class Frame extends React.Component< }; const drag = (tabId: string) => { + //start with internal drag and drop operation assumed + internalDnD = true; draggedTab = tabId; //inform of the tab dragstart document.dispatchEvent( @@ -208,7 +220,7 @@ export class Frame extends React.Component< const target: HTMLElement = ev.target as HTMLElement; console.log('tabDrop', ev, target, target.id); - if (draggedTab && target) { + if (internalDnD && draggedTab && target) { const tabId = draggedTab; //rewrite the tablist //find the selected tab, and pop it out of the list @@ -245,6 +257,16 @@ export class Frame extends React.Component< }, 100); draggedTab = null; + internalDnD = false; + } else { + //raise drop event for tear out + document.dispatchEvent( + new CustomEvent(TOPICS.DROP_TAB, { + detail: { + frameTarget: true, + }, + }), + ); } }; @@ -261,11 +283,17 @@ export class Frame extends React.Component< ); }; + const leaveTab = () => { + tabDragTimeout = window.setTimeout(() => { + internalDnD = false; + }, 1000); + }; + const dragEnd = (ev: SyntheticDragEvent) => { ev.preventDefault(); - console.log('dragEnd', draggedTab); - if (draggedTab) { + //if this is not an internal tab drag operation and this isn't the last tab in the window, allow tear out on drag end + if (draggedTab && !internalDnD && this.state.tabs.length > 1) { ev.stopPropagation(); console.log('tabDropped outside target', draggedTab); document.dispatchEvent( @@ -281,8 +309,9 @@ export class Frame extends React.Component< const tearOut = (ev: SyntheticDragEvent) => { ev.preventDefault(); //only tear out if there is more than one tab in the set + //only tear out if the 'internalDnD' flag is not set console.log('tearOut?', draggedTab, this.state.tabs.length); - if (draggedTab && this.state.tabs.length > 1) { + if (!internalDnD && draggedTab && this.state.tabs.length > 1) { ev.stopPropagation(); document.dispatchEvent( new CustomEvent(TOPICS.TEAR_OUT_TAB, { @@ -361,6 +390,7 @@ export class Frame extends React.Component< id={tab.tabId} iconPosition="end" onDrop={drop} + onDragLeave={leaveTab} onDragOver={allowDrop} onDragEnd={dragEnd} draggable="true"