22// SPDX-License-Identifier: Apache-2.0
33
44import { WaveUIMessagePart } from "@/app/aipanel/aitypes" ;
5+ import { waveAIHasSelection } from "@/app/aipanel/waveai-focus-utils" ;
56import { ErrorBoundary } from "@/app/element/errorboundary" ;
7+ import { focusManager } from "@/app/store/focusManager" ;
68import { atoms , getSettingsKeyAtom } from "@/app/store/global" ;
79import { globalStore } from "@/app/store/jotaiStore" ;
8- import { workspaceLayoutModel } from "@/app/workspace/workspace-layout-model" ;
10+ import { WorkspaceLayoutModel } from "@/app/workspace/workspace-layout-model" ;
911import { getWebServerEndpoint } from "@/util/endpoints" ;
12+ import { getElemAsStr } from "@/util/focusutil" ;
1013import { checkKeyPressed , keydownWrapper } from "@/util/keyutil" ;
1114import { cn } from "@/util/util" ;
1215import { useChat } from "@ai-sdk/react" ;
1316import { DefaultChatTransport } from "ai" ;
1417import * as jotai from "jotai" ;
15- import { memo , useEffect , useRef , useState } from "react" ;
18+ import { memo , useCallback , useEffect , useRef , useState } from "react" ;
1619import { createDataUrl , formatFileSizeError , isAcceptableFile , normalizeMimeType , validateFileSize } from "./ai-utils" ;
1720import { AIDroppedFiles } from "./aidroppedfiles" ;
1821import { AIPanelHeader } from "./aipanelheader" ;
@@ -37,9 +40,10 @@ const AIPanelComponentInner = memo(({ className, onClose }: AIPanelProps) => {
3740 const inputRef = useRef < AIPanelInputRef > ( null ) ;
3841 const isLayoutMode = jotai . useAtomValue ( atoms . controlShiftDelayAtom ) ;
3942 const showOverlayBlockNums = jotai . useAtomValue ( getSettingsKeyAtom ( "app:showoverlayblocknums" ) ) ?? true ;
40- const isFocused = jotai . useAtomValue ( atoms . waveAIFocusedAtom ) ;
43+ const focusType = jotai . useAtomValue ( focusManager . focusType ) ;
44+ const isFocused = focusType === "waveai" ;
4145 const telemetryEnabled = jotai . useAtomValue ( getSettingsKeyAtom ( "telemetry:enabled" ) ) ?? false ;
42- const isPanelVisible = jotai . useAtomValue ( workspaceLayoutModel . panelVisibleAtom ) ;
46+ const isPanelVisible = jotai . useAtomValue ( WorkspaceLayoutModel . getInstance ( ) . panelVisibleAtom ) ;
4347
4448 const { messages, sendMessage, status, setMessages, error } = useChat ( {
4549 transport : new DefaultChatTransport ( {
@@ -246,19 +250,27 @@ const AIPanelComponentInner = memo(({ className, onClose }: AIPanelProps) => {
246250 }
247251 } ;
248252
253+ const handleFocusCapture = useCallback ( ( event : React . FocusEvent ) => {
254+ console . log ( "Wave AI focus capture" , getElemAsStr ( event . target ) ) ;
255+ focusManager . requestWaveAIFocus ( ) ;
256+ } , [ ] ) ;
257+
249258 const handleClick = ( e : React . MouseEvent ) => {
250- // Check if the click target is an interactive element
251259 const target = e . target as HTMLElement ;
252260 const isInteractive = target . closest ( 'button, a, input, textarea, select, [role="button"], [tabindex]' ) ;
253261
254262 if ( isInteractive ) {
255263 return ;
256264 }
257265
258- // Use setTimeout to avoid interfering with other click actions
266+ const hasSelection = waveAIHasSelection ( ) ;
267+ if ( hasSelection ) {
268+ focusManager . requestWaveAIFocus ( ) ;
269+ return ;
270+ }
271+
259272 setTimeout ( ( ) => {
260- const selection = window . getSelection ( ) ;
261- if ( ! selection || selection . toString ( ) . length === 0 ) {
273+ if ( ! waveAIHasSelection ( ) ) {
262274 model . focusInput ( ) ;
263275 }
264276 } , 0 ) ;
@@ -268,6 +280,7 @@ const AIPanelComponentInner = memo(({ className, onClose }: AIPanelProps) => {
268280
269281 return (
270282 < div
283+ data-waveai-panel = "true"
271284 className = { cn (
272285 "bg-gray-900 flex flex-col relative h-[calc(100%-4px)] mt-1" ,
273286 className ,
@@ -279,6 +292,7 @@ const AIPanelComponentInner = memo(({ className, onClose }: AIPanelProps) => {
279292 borderBottomRightRadius : 10 ,
280293 borderBottomLeftRadius : 10 ,
281294 } }
295+ onFocusCapture = { handleFocusCapture }
282296 onDragOver = { handleDragOver }
283297 onDragEnter = { handleDragEnter }
284298 onDragLeave = { handleDragLeave }
0 commit comments