diff --git a/packages/jupyter-chat/package.json b/packages/jupyter-chat/package.json index 2723b9c9..81d42276 100644 --- a/packages/jupyter-chat/package.json +++ b/packages/jupyter-chat/package.json @@ -51,6 +51,7 @@ "@jupyterlab/codeeditor": "^4.2.0", "@jupyterlab/codemirror": "^4.2.0", "@jupyterlab/docmanager": "^4.2.0", + "@jupyterlab/docregistry": "^4.2.0", "@jupyterlab/filebrowser": "^4.2.0", "@jupyterlab/fileeditor": "^4.2.0", "@jupyterlab/notebook": "^4.2.0", @@ -62,6 +63,7 @@ "@lumino/disposable": "^2.0.0", "@lumino/polling": "^2.0.0", "@lumino/signaling": "^2.0.0", + "@lumino/widgets": "^2.0.0", "@mui/icons-material": "^7.3.2", "@mui/material": "^7.3.2", "clsx": "^2.1.0", diff --git a/packages/jupyter-chat/src/widgets/chat-widget.tsx b/packages/jupyter-chat/src/widgets/chat-widget.tsx index 0ea49239..4643fd3b 100644 --- a/packages/jupyter-chat/src/widgets/chat-widget.tsx +++ b/packages/jupyter-chat/src/widgets/chat-widget.tsx @@ -6,10 +6,12 @@ import { ReactWidget } from '@jupyterlab/apputils'; import { Cell } from '@jupyterlab/cells'; import { DirListing } from '@jupyterlab/filebrowser'; +import { DocumentWidget } from '@jupyterlab/docregistry'; import { ICell, isCode, isMarkdown, isRaw } from '@jupyterlab/nbformat'; import React from 'react'; import { Message } from '@lumino/messaging'; import { Drag } from '@lumino/dragdrop'; +import { Widget } from '@lumino/widgets'; import { Chat, IInputToolbarRegistry, MESSAGE_CLASS } from '../components'; import { chatIcon } from '../icons'; @@ -28,6 +30,9 @@ const FILE_BROWSER_MIME = 'application/x-jupyter-icontentsrich'; // MIME type constant for Notebook cell drag events const NOTEBOOK_CELL_MIME = 'application/vnd.jupyter.cells'; +// MIME type constant for TabBar file drag events +const TABBAR_FILE_MIME = 'application/vnd.lumino.widget-factory'; + // CSS class constants const INPUT_CONTAINER_CLASS = 'jp-chat-input-container'; const DRAG_HOVER_CLASS = 'jp-chat-drag-hover'; @@ -179,7 +184,9 @@ export class ChatWidget extends ReactWidget { private _canHandleDrop(event: Drag.Event): boolean { const types = event.mimeData.types(); return ( - types.includes(NOTEBOOK_CELL_MIME) || types.includes(FILE_BROWSER_MIME) + types.includes(NOTEBOOK_CELL_MIME) || + types.includes(FILE_BROWSER_MIME) || + types.includes(TABBAR_FILE_MIME) ); } @@ -202,6 +209,8 @@ export class ChatWidget extends ReactWidget { this._processCellDrop(event); } else if (event.mimeData.hasData(FILE_BROWSER_MIME)) { this._processFileDrop(event); + } else if (event.mimeData.hasData(TABBAR_FILE_MIME)) { + this._processTabDrop(event); } } catch (error) { console.error('Error processing drop:', error); @@ -321,6 +330,40 @@ export class ChatWidget extends ReactWidget { } } + /** + * Process dropped tabBar files + */ + private _processTabDrop(event: Drag.Event) { + const factory = event.mimeData.getData(TABBAR_FILE_MIME) as () => Widget; + if (!factory) { + console.warn('No factory in drag event'); + return; + } + + const widget = factory(); + if (!widget || !(widget instanceof DocumentWidget)) { + console.warn('No file associated to the element'); + return; + } + + const path = widget.context.path; + if (!path) { + console.warn('Widget has no path'); + return; + } + + const mimetype = + widget.context.model?.mimeType || 'application/octet-stream'; + const attachment: IFileAttachment = { + type: 'file', + value: path, + mimetype + }; + + const inputModel = this._getInputFromEvent(event); + inputModel?.addAttachment?.(attachment); + } + /** * Find the notebook path for a cell by searching through active and open notebooks */ diff --git a/yarn.lock b/yarn.lock index 90985dfa..b6676615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2309,6 +2309,7 @@ __metadata: "@jupyterlab/codeeditor": ^4.2.0 "@jupyterlab/codemirror": ^4.2.0 "@jupyterlab/docmanager": ^4.2.0 + "@jupyterlab/docregistry": ^4.2.0 "@jupyterlab/filebrowser": ^4.2.0 "@jupyterlab/fileeditor": ^4.2.0 "@jupyterlab/notebook": ^4.2.0 @@ -2321,6 +2322,7 @@ __metadata: "@lumino/disposable": ^2.0.0 "@lumino/polling": ^2.0.0 "@lumino/signaling": ^2.0.0 + "@lumino/widgets": ^2.0.0 "@mui/icons-material": ^7.3.2 "@mui/material": ^7.3.2 "@types/jest": ^29.2.0