| ... | @@ -343,6 +343,7 @@ import { | ... | @@ -343,6 +343,7 @@ import { |
| 343 | } from "./chat/draftHeroTransition"; | 343 | } from "./chat/draftHeroTransition"; |
| 344 | import { | 344 | import { |
| 345 | MAX_HIDDEN_MOUNTED_TERMINAL_THREADS, | 345 | MAX_HIDDEN_MOUNTED_TERMINAL_THREADS, |
| | 346 | agentControlledBrowserCloseConfirmation, |
| 346 | branchMismatchKey, | 347 | branchMismatchKey, |
| 347 | buildExpiredTerminalContextToastCopy, | 348 | buildExpiredTerminalContextToastCopy, |
| 348 | buildLocalDraftThread, | 349 | buildLocalDraftThread, |
| ... | @@ -3872,6 +3873,27 @@ function ChatViewContent(props: ChatViewProps) { | ... | @@ -3872,6 +3873,27 @@ function ChatViewContent(props: ChatViewProps) { |
| 3872 | storeCloseTerminal, | 3873 | storeCloseTerminal, |
| 3873 | ], | 3874 | ], |
| 3874 | ); | 3875 | ); |
| | 3876 | const closeAfterAgentBrowserConfirmation = useCallback( |
| | 3877 | (surfaces: readonly RightPanelSurface[], closeSurfaces: () => void) => { |
| | 3878 | const message = agentControlledBrowserCloseConfirmation( |
| | 3879 | surfaces, |
| | 3880 | activePreviewState.desktopByTabId, |
| | 3881 | ); |
| | 3882 | if (!message) { |
| | 3883 | closeSurfaces(); |
| | 3884 | return; |
| | 3885 | } |
| | 3886 | const localApi = readLocalApi(); |
| | 3887 | if (!localApi) return; |
| | 3888 | void localApi.dialogs.confirm(message, { variant: "destructive" }).then( |
| | 3889 | (confirmed) => { |
| | 3890 | if (confirmed) closeSurfaces(); |
| | 3891 | }, |
| | 3892 | () => undefined, |
| | 3893 | ); |
| | 3894 | }, |
| | 3895 | [activePreviewState.desktopByTabId], |
| | 3896 | ); |
| 3875 | const syncActivePreviewSurface = useCallback(() => { | 3897 | const syncActivePreviewSurface = useCallback(() => { |
| 3876 | if (!activeThreadRef) return; | 3898 | if (!activeThreadRef) return; |
| 3877 | const nextActiveSurface = selectActiveRightPanelSurface( | 3899 | const nextActiveSurface = selectActiveRightPanelSurface( |
| ... | @@ -3882,14 +3904,26 @@ function ChatViewContent(props: ChatViewProps) { | ... | @@ -3882,14 +3904,26 @@ function ChatViewContent(props: ChatViewProps) { |
| 3882 | setActivePreviewTab(activeThreadRef, nextActiveSurface.resourceId); | 3904 | setActivePreviewTab(activeThreadRef, nextActiveSurface.resourceId); |
| 3883 | } | 3905 | } |
| 3884 | }, [activeThreadRef]); | 3906 | }, [activeThreadRef]); |
| | 3907 | const finishRightPanelSurfaceClose = useCallback( |
| | 3908 | (surfaces: readonly RightPanelSurface[]) => { |
| | 3909 | if (!activeThreadRef) return; |
| | 3910 | cleanupRightPanelSurfaces(surfaces); |
| | 3911 | const store = useRightPanelStore.getState(); |
| | 3912 | for (const surface of surfaces) { |
| | 3913 | store.closeSurface(activeThreadRef, surface.id); |
| | 3914 | } |
| | 3915 | syncActivePreviewSurface(); |
| | 3916 | }, |
| | 3917 | [activeThreadRef, cleanupRightPanelSurfaces, syncActivePreviewSurface], |
| | 3918 | ); |
| 3885 | const closeRightPanelSurface = useCallback( | 3919 | const closeRightPanelSurface = useCallback( |
| 3886 | (surface: RightPanelSurface) => { | 3920 | (surface: RightPanelSurface) => { |
| 3887 | if (!activeThreadRef) return; | 3921 | if (!activeThreadRef) return; |
| 3888 | const finishClose = () => { | 3922 | const finishClose = () => finishRightPanelSurfaceClose([surface]); |
| 3889 | cleanupRightPanelSurfaces([surface]); | 3923 | if (surface.kind === "preview") { |
| 3890 | useRightPanelStore.getState().closeSurface(activeThreadRef, surface.id); | 3924 | closeAfterAgentBrowserConfirmation([surface], finishClose); |
| 3891 | syncActivePreviewSurface(); | 3925 | return; |
| 3892 | }; | 3926 | } |
| 3893 | if (surface.kind !== "terminal") { | 3927 | if (surface.kind !== "terminal") { |
| 3894 | finishClose(); | 3928 | finishClose(); |
| 3895 | return; | 3929 | return; |
| ... | @@ -3909,23 +3943,22 @@ function ChatViewContent(props: ChatViewProps) { | ... | @@ -3909,23 +3943,22 @@ function ChatViewContent(props: ChatViewProps) { |
| 3909 | [ | 3943 | [ |
| 3910 | activeThreadRef, | 3944 | activeThreadRef, |
| 3911 | activeTerminalLabelsById, | 3945 | activeTerminalLabelsById, |
| 3912 | cleanupRightPanelSurfaces, | 3946 | closeAfterAgentBrowserConfirmation, |
| 3913 | syncActivePreviewSurface, | 3947 | finishRightPanelSurfaceClose, |
| 3914 | ], | 3948 | ], |
| 3915 | ); | 3949 | ); |
| 3916 | const closeOtherRightPanelSurfaces = useCallback( | 3950 | const closeOtherRightPanelSurfaces = useCallback( |
| 3917 | (surface: RightPanelSurface) => { | 3951 | (surface: RightPanelSurface) => { |
| 3918 | if (!activeThreadRef) return; | 3952 | if (!activeThreadRef) return; |
| 3919 | const surfaces = rightPanelState.surfaces.filter((entry) => entry.id !== surface.id); | 3953 | const surfaces = rightPanelState.surfaces.filter((entry) => entry.id !== surface.id); |
| 3920 | cleanupRightPanelSurfaces(surfaces); | 3954 | const finishClose = () => finishRightPanelSurfaceClose(surfaces); |
| 3921 | useRightPanelStore.getState().closeOtherSurfaces(activeThreadRef, surface.id); | 3955 | closeAfterAgentBrowserConfirmation(surfaces, finishClose); |
| 3922 | syncActivePreviewSurface(); | | |
| 3923 | }, | 3956 | }, |
| 3924 | [ | 3957 | [ |
| 3925 | activeThreadRef, | 3958 | activeThreadRef, |
| 3926 | cleanupRightPanelSurfaces, | 3959 | closeAfterAgentBrowserConfirmation, |
| | 3960 | finishRightPanelSurfaceClose, |
| 3927 | rightPanelState.surfaces, | 3961 | rightPanelState.surfaces, |
| 3928 | syncActivePreviewSurface, | | |
| 3929 | ], | 3962 | ], |
| 3930 | ); | 3963 | ); |
| 3931 | const closeRightPanelSurfacesToRight = useCallback( | 3964 | const closeRightPanelSurfacesToRight = useCallback( |
| ... | @@ -3934,22 +3967,26 @@ function ChatViewContent(props: ChatViewProps) { | ... | @@ -3934,22 +3967,26 @@ function ChatViewContent(props: ChatViewProps) { |
| 3934 | const surfaceIndex = rightPanelState.surfaces.findIndex((entry) => entry.id === surface.id); | 3967 | const surfaceIndex = rightPanelState.surfaces.findIndex((entry) => entry.id === surface.id); |
| 3935 | if (surfaceIndex < 0) return; | 3968 | if (surfaceIndex < 0) return; |
| 3936 | const surfaces = rightPanelState.surfaces.slice(surfaceIndex + 1); | 3969 | const surfaces = rightPanelState.surfaces.slice(surfaceIndex + 1); |
| 3937 | cleanupRightPanelSurfaces(surfaces); | 3970 | const finishClose = () => finishRightPanelSurfaceClose(surfaces); |
| 3938 | useRightPanelStore.getState().closeSurfacesToRight(activeThreadRef, surface.id); | 3971 | closeAfterAgentBrowserConfirmation(surfaces, finishClose); |
| 3939 | syncActivePreviewSurface(); | | |
| 3940 | }, | 3972 | }, |
| 3941 | [ | 3973 | [ |
| 3942 | activeThreadRef, | 3974 | activeThreadRef, |
| 3943 | cleanupRightPanelSurfaces, | 3975 | closeAfterAgentBrowserConfirmation, |
| | 3976 | finishRightPanelSurfaceClose, |
| 3944 | rightPanelState.surfaces, | 3977 | rightPanelState.surfaces, |
| 3945 | syncActivePreviewSurface, | | |
| 3946 | ], | 3978 | ], |
| 3947 | ); | 3979 | ); |
| 3948 | const closeAllRightPanelSurfaces = useCallback(() => { | 3980 | const closeAllRightPanelSurfaces = useCallback(() => { |
| 3949 | if (!activeThreadRef) return; | 3981 | if (!activeThreadRef) return; |
| 3950 | cleanupRightPanelSurfaces(rightPanelState.surfaces); | 3982 | const finishClose = () => finishRightPanelSurfaceClose(rightPanelState.surfaces); |
| 3951 | useRightPanelStore.getState().closeAllSurfaces(activeThreadRef); | 3983 | closeAfterAgentBrowserConfirmation(rightPanelState.surfaces, finishClose); |
| 3952 | }, [activeThreadRef, cleanupRightPanelSurfaces, rightPanelState.surfaces]); | 3984 | }, [ |
| | 3985 | activeThreadRef, |
| | 3986 | closeAfterAgentBrowserConfirmation, |
| | 3987 | finishRightPanelSurfaceClose, |
| | 3988 | rightPanelState.surfaces, |
| | 3989 | ]); |
| 3953 | const copyRightPanelFilePath = useCallback((relativePath: string) => { | 3990 | const copyRightPanelFilePath = useCallback((relativePath: string) => { |
| 3954 | if (typeof window === "undefined" || !navigator.clipboard?.writeText) { | 3991 | if (typeof window === "undefined" || !navigator.clipboard?.writeText) { |
| 3955 | toastManager.add( | 3992 | toastManager.add( |