11import { Effect } from "effect"
2- import type { CSSProperties , JSX } from "react"
2+ import { type CSSProperties , type JSX , useEffect , useState } from "react"
33
44import { deleteTerminalSessionByPath } from "./api.js"
55import { canOpenProjectBrowser } from "./app-ready-browser-openable.js"
66import type { ReadyLayoutProps } from "./app-ready-layout.js"
77import { Box , Text } from "./elements.js"
8+ import { TaskPanel } from "./panel-tasks.js"
89import { TerminalPanel } from "./panel-terminal.js"
910import { type BrowserScreen , projectPickerScreen } from "./screen.js"
1011import { shouldShowTerminalTabs } from "./terminal-mobile-layout.js"
1112import { terminalSessionId } from "./terminal-state.js"
1213import type { ActiveTerminalSession } from "./terminal.js"
1314
15+ type TerminalWorkspaceView = "terminal" | "tasks"
16+
1417type TerminalScreenProps = Pick <
1518 ReadyLayoutProps ,
1619 | "activeTerminalSessionId"
1720 | "onApplyProjectById"
1821 | "onOpenProjectBrowserById"
1922 | "onOpenProjectTaskManagerById"
2023 | "onOpenProjectTerminalById"
24+ | "onLoadProjectTaskLogs"
25+ | "onProjectTasksIncludeDefaultChange"
26+ | "onRefreshProjectTasks"
2127 | "onSelectTerminal"
2228 | "onSetActiveScreen"
29+ | "onStopProjectTask"
2330 | "onTerminalClose"
2431 | "onTerminalMessage"
32+ | "project"
2533 | "projectBrowser"
34+ | "projectTaskLogs"
35+ | "projectTasks"
36+ | "projectTasksIncludeDefault"
37+ | "selectedProjectSummary"
2638 | "terminalSessions"
2739 | "viewportLayout"
2840>
@@ -34,13 +46,24 @@ type TerminalPaneProps =
3446 | "onOpenProjectBrowserById"
3547 | "onOpenProjectTaskManagerById"
3648 | "onOpenProjectTerminalById"
49+ | "onLoadProjectTaskLogs"
50+ | "onProjectTasksIncludeDefaultChange"
51+ | "onRefreshProjectTasks"
3752 | "onSetActiveScreen"
53+ | "onStopProjectTask"
3854 | "onTerminalClose"
3955 | "onTerminalMessage"
56+ | "project"
4057 | "projectBrowser"
58+ | "projectTaskLogs"
59+ | "projectTasks"
60+ | "projectTasksIncludeDefault"
61+ | "selectedProjectSummary"
4162 | "viewportLayout"
4263 >
4364 & {
65+ readonly taskManagerOpen : boolean
66+ readonly onCloseTaskManager : ( ) => void
4467 readonly singleSession : boolean
4568 readonly terminalSession : ActiveTerminalSession
4669 }
@@ -72,8 +95,83 @@ const activeTerminalPaneStyle: CSSProperties = {
7295 overflow : "hidden"
7396}
7497
98+ const taskManagerBodyStyle : CSSProperties = {
99+ background : "#080a0d" ,
100+ boxSizing : "border-box" ,
101+ color : "#d6e5f7" ,
102+ height : "100%" ,
103+ overflow : "auto" ,
104+ padding : "10px"
105+ }
106+
107+ const taskManagerToolbarStyle : CSSProperties = {
108+ alignItems : "center" ,
109+ display : "flex" ,
110+ justifyContent : "flex-end" ,
111+ marginBottom : "10px"
112+ }
113+
114+ const taskManagerReturnButtonStyle : CSSProperties = {
115+ background : "#171d24" ,
116+ border : "1px solid #3a4652" ,
117+ borderRadius : "8px" ,
118+ color : "#d6e5f7" ,
119+ cursor : "pointer" ,
120+ font : "inherit" ,
121+ padding : "6px 10px"
122+ }
123+
75124const terminalTabLabel = ( session : ActiveTerminalSession ) : string => session . browserProjectName ?? session . header
76125
126+ const TerminalTaskManagerBody = (
127+ {
128+ onClose,
129+ onLoadProjectTaskLogs,
130+ onProjectTasksIncludeDefaultChange,
131+ onRefreshProjectTasks,
132+ onStopProjectTask,
133+ project,
134+ projectTaskLogs,
135+ projectTasks,
136+ projectTasksIncludeDefault,
137+ selectedProjectSummary
138+ } :
139+ & Pick <
140+ TerminalScreenProps ,
141+ | "onLoadProjectTaskLogs"
142+ | "onProjectTasksIncludeDefaultChange"
143+ | "onRefreshProjectTasks"
144+ | "onStopProjectTask"
145+ | "project"
146+ | "projectTaskLogs"
147+ | "projectTasks"
148+ | "projectTasksIncludeDefault"
149+ | "selectedProjectSummary"
150+ >
151+ & {
152+ readonly onClose : ( ) => void
153+ }
154+ ) : JSX . Element => (
155+ < div style = { taskManagerBodyStyle } >
156+ < div style = { taskManagerToolbarStyle } >
157+ < button onClick = { onClose } style = { taskManagerReturnButtonStyle } type = "button" >
158+ Terminal
159+ </ button >
160+ </ div >
161+ < TaskPanel
162+ includeDefault = { projectTasksIncludeDefault }
163+ logs = { projectTaskLogs }
164+ onIncludeDefaultChange = { onProjectTasksIncludeDefaultChange }
165+ onLoadLogs = { onLoadProjectTaskLogs }
166+ onRefreshTasks = { onRefreshProjectTasks }
167+ onStopTask = { onStopProjectTask }
168+ project = { project }
169+ selectedProjectSummary = { selectedProjectSummary }
170+ snapshot = { projectTasks }
171+ />
172+ </ div >
173+ )
174+
77175const TerminalTab = (
78176 {
79177 active,
@@ -211,14 +309,25 @@ const TerminalTabs = (
211309const TerminalPane = (
212310 {
213311 onApplyProjectById,
312+ onCloseTaskManager,
313+ onLoadProjectTaskLogs,
214314 onOpenProjectBrowserById,
215315 onOpenProjectTaskManagerById,
216316 onOpenProjectTerminalById,
317+ onProjectTasksIncludeDefaultChange,
318+ onRefreshProjectTasks,
217319 onSetActiveScreen,
320+ onStopProjectTask,
218321 onTerminalClose,
219322 onTerminalMessage,
323+ project,
220324 projectBrowser,
325+ projectTaskLogs,
326+ projectTasks,
327+ projectTasksIncludeDefault,
328+ selectedProjectSummary,
221329 singleSession,
330+ taskManagerOpen,
222331 terminalSession,
223332 viewportLayout
224333 } : TerminalPaneProps
@@ -227,6 +336,22 @@ const TerminalPane = (
227336 const browserProjectId = terminalSession . browserProjectId
228337 const browserProjectKey = terminalSession . browserProjectKey
229338 const canOpenBrowser = canOpenProjectBrowser ( projectBrowser , browserProjectId )
339+ const bodyContent = taskManagerOpen && browserProjectId !== undefined
340+ ? (
341+ < TerminalTaskManagerBody
342+ onClose = { onCloseTaskManager }
343+ onLoadProjectTaskLogs = { onLoadProjectTaskLogs }
344+ onProjectTasksIncludeDefaultChange = { onProjectTasksIncludeDefaultChange }
345+ onRefreshProjectTasks = { onRefreshProjectTasks }
346+ onStopProjectTask = { onStopProjectTask }
347+ project = { project }
348+ projectTaskLogs = { projectTaskLogs }
349+ projectTasks = { projectTasks }
350+ projectTasksIncludeDefault = { projectTasksIncludeDefault }
351+ selectedProjectSummary = { selectedProjectSummary }
352+ />
353+ )
354+ : undefined
230355 const detachTerminalSession = ( ) : void => {
231356 onTerminalClose ( sessionId )
232357 if ( singleSession ) {
@@ -236,6 +361,7 @@ const TerminalPane = (
236361 return (
237362 < div style = { activeTerminalPaneStyle } >
238363 < TerminalPanel
364+ bodyContent = { bodyContent }
239365 keyboardOpen = { viewportLayout . keyboardOpen }
240366 mobileMode = { viewportLayout . mode === "mobile" }
241367 onAttachFailure = { ( ) => {
@@ -279,12 +405,16 @@ const TerminalPane = (
279405}
280406
281407export const TerminalScreen = ( props : TerminalScreenProps ) : JSX . Element | null => {
282- if ( props . terminalSessions . length === 0 ) {
283- return null
284- }
408+ const [ terminalView , setTerminalView ] = useState < TerminalWorkspaceView > ( "terminal" )
285409 const mobileMode = props . viewportLayout . mode === "mobile"
286410 const activeSessionId = resolveActiveTerminalSessionId ( props . terminalSessions , props . activeTerminalSessionId )
287411 const activeSession = props . terminalSessions . find ( ( session ) => terminalSessionId ( session ) === activeSessionId )
412+ useEffect ( ( ) => {
413+ setTerminalView ( "terminal" )
414+ } , [ activeSession ?. browserProjectId , activeSessionId ] )
415+ if ( props . terminalSessions . length === 0 ) {
416+ return null
417+ }
288418 return (
289419 < Box flexDirection = "column" flexGrow = { 1 } gap = { mobileMode ? "4px" : 1 } minHeight = { 0 } overflow = "hidden" >
290420 { shouldShowTerminalTabs ( mobileMode , props . terminalSessions . length )
@@ -305,14 +435,30 @@ export const TerminalScreen = (props: TerminalScreenProps): JSX.Element | null =
305435 < TerminalPane
306436 key = { terminalSessionId ( activeSession ) }
307437 onApplyProjectById = { props . onApplyProjectById }
438+ onCloseTaskManager = { ( ) => {
439+ setTerminalView ( "terminal" )
440+ } }
441+ onLoadProjectTaskLogs = { props . onLoadProjectTaskLogs }
308442 onOpenProjectBrowserById = { props . onOpenProjectBrowserById }
309- onOpenProjectTaskManagerById = { props . onOpenProjectTaskManagerById }
443+ onOpenProjectTaskManagerById = { ( projectId ) => {
444+ setTerminalView ( "tasks" )
445+ props . onOpenProjectTaskManagerById ( projectId )
446+ } }
310447 onOpenProjectTerminalById = { props . onOpenProjectTerminalById }
448+ onProjectTasksIncludeDefaultChange = { props . onProjectTasksIncludeDefaultChange }
449+ onRefreshProjectTasks = { props . onRefreshProjectTasks }
311450 onSetActiveScreen = { props . onSetActiveScreen }
451+ onStopProjectTask = { props . onStopProjectTask }
312452 onTerminalClose = { props . onTerminalClose }
313453 onTerminalMessage = { props . onTerminalMessage }
454+ project = { props . project }
314455 projectBrowser = { props . projectBrowser }
456+ projectTaskLogs = { props . projectTaskLogs }
457+ projectTasks = { props . projectTasks }
458+ projectTasksIncludeDefault = { props . projectTasksIncludeDefault }
459+ selectedProjectSummary = { props . selectedProjectSummary }
315460 singleSession = { props . terminalSessions . length === 1 }
461+ taskManagerOpen = { terminalView === "tasks" }
316462 terminalSession = { activeSession }
317463 viewportLayout = { props . viewportLayout }
318464 />
0 commit comments