@@ -91,6 +91,7 @@ import PlanSidebar from "./PlanSidebar";
9191import ThreadTerminalDrawer from "./ThreadTerminalDrawer" ;
9292import { SpotifyPlayerDrawer } from "./SpotifyPlayer" ;
9393import {
94+ AtSignIcon ,
9495 BotIcon ,
9596 ChevronDownIcon ,
9697 ChevronLeftIcon ,
@@ -345,6 +346,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
345346 const promptRef = useRef ( prompt ) ;
346347 const [ showScrollToBottom , setShowScrollToBottom ] = useState ( false ) ;
347348 const [ isDragOverComposer , setIsDragOverComposer ] = useState ( false ) ;
349+ const [ dragOverType , setDragOverType ] = useState < "files" | "tree-path" > ( "files" ) ;
348350 const [ expandedImage , setExpandedImage ] = useState < ExpandedImagePreview | null > ( null ) ;
349351 const [ optimisticUserMessages , setOptimisticUserMessages ] = useState < ChatMessage [ ] > ( [ ] ) ;
350352 const optimisticUserMessagesRef = useRef ( optimisticUserMessages ) ;
@@ -2444,17 +2446,25 @@ export default function ChatView({ threadId }: ChatViewProps) {
24442446 addComposerImages ( imageFiles ) ;
24452447 } ;
24462448
2449+ const isAcceptedDragType = ( dataTransfer : DataTransfer ) =>
2450+ dataTransfer . types . includes ( "Files" ) ||
2451+ dataTransfer . types . includes ( "application/x-okcode-tree-path" ) ;
2452+
2453+ const isDragTreePath = ( dataTransfer : DataTransfer ) =>
2454+ dataTransfer . types . includes ( "application/x-okcode-tree-path" ) ;
2455+
24472456 const onComposerDragEnter = ( event : React . DragEvent < HTMLDivElement > ) => {
2448- if ( ! event . dataTransfer . types . includes ( "Files" ) ) {
2457+ if ( ! isAcceptedDragType ( event . dataTransfer ) ) {
24492458 return ;
24502459 }
24512460 event . preventDefault ( ) ;
24522461 dragDepthRef . current += 1 ;
2462+ setDragOverType ( isDragTreePath ( event . dataTransfer ) ? "tree-path" : "files" ) ;
24532463 setIsDragOverComposer ( true ) ;
24542464 } ;
24552465
24562466 const onComposerDragOver = ( event : React . DragEvent < HTMLDivElement > ) => {
2457- if ( ! event . dataTransfer . types . includes ( "Files" ) ) {
2467+ if ( ! isAcceptedDragType ( event . dataTransfer ) ) {
24582468 return ;
24592469 }
24602470 event . preventDefault ( ) ;
@@ -2463,7 +2473,7 @@ export default function ChatView({ threadId }: ChatViewProps) {
24632473 } ;
24642474
24652475 const onComposerDragLeave = ( event : React . DragEvent < HTMLDivElement > ) => {
2466- if ( ! event . dataTransfer . types . includes ( "Files" ) ) {
2476+ if ( ! isAcceptedDragType ( event . dataTransfer ) ) {
24672477 return ;
24682478 }
24692479 event . preventDefault ( ) ;
@@ -2478,12 +2488,27 @@ export default function ChatView({ threadId }: ChatViewProps) {
24782488 } ;
24792489
24802490 const onComposerDrop = ( event : React . DragEvent < HTMLDivElement > ) => {
2481- if ( ! event . dataTransfer . types . includes ( "Files" ) ) {
2491+ if ( ! isAcceptedDragType ( event . dataTransfer ) ) {
24822492 return ;
24832493 }
24842494 event . preventDefault ( ) ;
24852495 dragDepthRef . current = 0 ;
24862496 setIsDragOverComposer ( false ) ;
2497+
2498+ // Handle file tree path drops — insert as @mention context
2499+ if ( isDragTreePath ( event . dataTransfer ) ) {
2500+ const treePath = event . dataTransfer . getData ( "application/x-okcode-tree-path" ) ;
2501+ if ( treePath ) {
2502+ const snapshot = readComposerSnapshot ( ) ;
2503+ const mention = `@${ treePath } ` ;
2504+ // Insert at the current cursor position
2505+ applyPromptReplacement ( snapshot . cursor , snapshot . cursor , mention ) ;
2506+ }
2507+ focusComposer ( ) ;
2508+ return ;
2509+ }
2510+
2511+ // Handle image file drops
24872512 const files = Array . from ( event . dataTransfer . files ) ;
24882513 addComposerImages ( files ) ;
24892514 focusComposer ( ) ;
@@ -4007,8 +4032,17 @@ export default function ChatView({ threadId }: ChatViewProps) {
40074032 { isDragOverComposer && (
40084033 < div className = "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-[22px] border-2 border-dashed border-primary/60 bg-primary/5" >
40094034 < div className = "flex items-center gap-2 rounded-lg bg-background/90 px-4 py-2 text-sm font-medium text-primary shadow-sm" >
4010- < ImagePlusIcon className = "size-4" />
4011- Drop images to attach
4035+ { dragOverType === "tree-path" ? (
4036+ < >
4037+ < AtSignIcon className = "size-4" />
4038+ Drop to add as context
4039+ </ >
4040+ ) : (
4041+ < >
4042+ < ImagePlusIcon className = "size-4" />
4043+ Drop images to attach
4044+ </ >
4045+ ) }
40124046 </ div >
40134047 </ div >
40144048 ) }
0 commit comments